Replace anonymous classes with lambdas when possible.

Most of these changes are for anonymous `SkyFunction` subclasses, and so they were enabled by commit 927b625e15d2beac5bfecae1d3c05783151a8ff3. (janakr@ therefore had recommended these changes during offline discussion about commit d789eda7fb9ee1b24ff643d65fd5794a920d61af.)

Also make a few minor code cleanups.

PiperOrigin-RevId: 414553549
diff --git a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
index ffb21f8..7b47630 100644
--- a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
@@ -54,6 +54,7 @@
 import com.google.devtools.build.skyframe.NotifyingHelper.Listener;
 import com.google.devtools.build.skyframe.NotifyingHelper.Order;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
+import com.google.devtools.build.skyframe.SkyFunction.Restart;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.ThinNodeEntry.DirtyType;
 import com.google.devtools.build.skyframe.proto.GraphInconsistency.Inconsistency;
@@ -249,32 +250,26 @@
     tester
         .getOrCreate("top")
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                env.getValue(toSkyKey("sleepyValue"));
-                try {
-                  env.getValueOrThrow(toSkyKey("badValue"), SomeErrorException.class);
-                } catch (SomeErrorException e) {
-                  // In order to trigger this bug, we need to request a dep on an already computed
-                  // value.
-                  env.getValue(toSkyKey("otherValue1"));
-                }
-                if (!env.valuesMissing()) {
-                  throw new AssertionError("SleepyValue should always be unavailable");
-                }
-                return null;
+            (skyKey, env) -> {
+              env.getValue(toSkyKey("sleepyValue"));
+              try {
+                env.getValueOrThrow(toSkyKey("badValue"), SomeErrorException.class);
+              } catch (SomeErrorException e) {
+                // In order to trigger this bug, we need to request a dep on an already computed
+                // value.
+                env.getValue(toSkyKey("otherValue1"));
               }
+              if (!env.valuesMissing()) {
+                throw new AssertionError("SleepyValue should always be unavailable");
+              }
+              return null;
             });
     tester
         .getOrCreate("sleepyValue")
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                Thread.sleep(99999);
-                throw new AssertionError("I should have been interrupted");
-              }
+            (skyKey, env) -> {
+              Thread.sleep(99999);
+              throw new AssertionError("I should have been interrupted");
             });
     tester.getOrCreate("badValue").addDependency("otherValue1").setHasError(true);
     tester.getOrCreate("otherValue1").setConstantValue(new StringValue("otherVal1"));
@@ -293,16 +288,13 @@
     tester
         .getOrCreate(topKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                if (counter.getAndIncrement() > 0) {
-                  deps.addAll(env.getTemporaryDirectDeps().get(0));
-                } else {
-                  assertThat(env.getTemporaryDirectDeps().listSize()).isEqualTo(0);
-                }
-                return env.getValue(bottomKey);
+            (skyKey, env) -> {
+              if (counter.getAndIncrement() > 0) {
+                deps.addAll(env.getTemporaryDirectDeps().get(0));
+              } else {
+                assertThat(env.getTemporaryDirectDeps().listSize()).isEqualTo(0);
               }
+              return env.getValue(bottomKey);
             });
     tester.getOrCreate(bottomKey).setConstantValue(bottomValue);
     EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, "top");
@@ -867,25 +859,22 @@
     final SkyKey mid = GraphTester.toSkyKey("zzmid");
     final CountDownLatch valueSet = new CountDownLatch(1);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (!key.equals(mid)) {
-              return;
-            }
-            switch (type) {
-              case ADD_REVERSE_DEP:
-                if (context == null) {
-                  // Context is null when we are enqueuing this value as a top-level job.
-                  TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(valueSet, "value not set");
-                }
-                break;
-              case SET_VALUE:
-                valueSet.countDown();
-                break;
-              default:
-                break;
-            }
+        (key, type, order, context) -> {
+          if (!key.equals(mid)) {
+            return;
+          }
+          switch (type) {
+            case ADD_REVERSE_DEP:
+              if (context == null) {
+                // Context is null when we are enqueuing this value as a top-level job.
+                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(valueSet, "value not set");
+              }
+              break;
+            case SET_VALUE:
+              valueSet.countDown();
+              break;
+            default:
+              break;
           }
         },
         /*deterministic=*/ true);
@@ -1432,21 +1421,16 @@
     // We don't do anything on the first build.
     final AtomicBoolean secondBuild = new AtomicBoolean(false);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (!secondBuild.get()) {
-              return;
-            }
-            if (key.equals(otherTop) && type == EventType.SIGNAL) {
-              // otherTop is being signaled that dep1 is done. Tell the error value that it is
-              // ready, then wait until the error is thrown, so that otherTop's builder is not
-              // re-entered.
-              valuesReady.countDown();
-              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                  errorThrown, "error not thrown");
-              return;
-            }
+        (key, type, order, context) -> {
+          if (!secondBuild.get()) {
+            return;
+          }
+          if (key.equals(otherTop) && type == EventType.SIGNAL) {
+            // otherTop is being signaled that dep1 is done. Tell the error value that it is ready,
+            // then wait until the error is thrown, so that otherTop's builder is not re-entered.
+            valuesReady.countDown();
+            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(errorThrown, "error not thrown");
+            return;
           }
         },
         /*deterministic=*/ true);
@@ -1459,16 +1443,13 @@
     tester
         .getOrCreate(otherTop)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                env.getValue(dep1);
-                if (env.valuesMissing()) {
-                  return null;
-                }
-                env.getValue(dep2);
-                return env.valuesMissing() ? null : new StringValue("otherTop");
+            (skyKey, env) -> {
+              env.getValue(dep1);
+              if (env.valuesMissing()) {
+                return null;
               }
+              env.getValue(dep2);
+              return env.valuesMissing() ? null : new StringValue("otherTop");
             });
     // Prime the graph with otherTop, so we can dirty it next build.
     assertThat(tester.evalAndGet(/*keepGoing=*/ false, otherTop))
@@ -1667,20 +1648,17 @@
       tester
           .getOrCreate("subKey" + i)
           .setComputedValue(
-              new ValueComputer() {
-                @Override
-                public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) {
-                  int val = inProgressCount.incrementAndGet();
-                  synchronized (lock) {
-                    if (val > maxValue[0]) {
-                      maxValue[0] = val;
-                    }
+              (deps, env) -> {
+                int val = inProgressCount.incrementAndGet();
+                synchronized (lock) {
+                  if (val > maxValue[0]) {
+                    maxValue[0] = val;
                   }
-                  Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
-
-                  inProgressCount.decrementAndGet();
-                  return new StringValue("abc");
                 }
+                Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
+
+                inProgressCount.decrementAndGet();
+                return new StringValue("abc");
               });
     }
     topLevelBuilder.setConstantValue(new StringValue("xyz"));
@@ -2141,16 +2119,12 @@
     tester
         .getOrCreate(topKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                env.getValues(ImmutableList.of(errorKey, midKey, mid2Key));
-                if (env.valuesMissing()) {
-                  return null;
-                }
-                return new StringValue("top");
+            (skyKey, env) -> {
+              env.getValues(ImmutableList.of(errorKey, midKey, mid2Key));
+              if (env.valuesMissing()) {
+                return null;
               }
+              return new StringValue("top");
             });
 
     // Assert that build fails and "error" really is in error.
@@ -2182,23 +2156,19 @@
     tester
         .getOrCreate(topKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                SkyKeyValue val =
-                    ((SkyKeyValue)
-                        env.getValues(ImmutableList.of(groupDepA, groupDepB)).get(groupDepA));
-                if (env.valuesMissing()) {
-                  return null;
-                }
-                try {
-                  env.getValueOrThrow(val.key, SomeErrorException.class);
-                } catch (SomeErrorException e) {
-                  throw new GenericFunctionException(e, Transience.PERSISTENT);
-                }
-                return env.valuesMissing() ? null : new StringValue("top");
+            (skyKey, env) -> {
+              SkyKeyValue val =
+                  ((SkyKeyValue)
+                      env.getValues(ImmutableList.of(groupDepA, groupDepB)).get(groupDepA));
+              if (env.valuesMissing()) {
+                return null;
               }
+              try {
+                env.getValueOrThrow(val.key, SomeErrorException.class);
+              } catch (SomeErrorException e) {
+                throw new GenericFunctionException(e, Transience.PERSISTENT);
+              }
+              return env.valuesMissing() ? null : new StringValue("top");
             });
 
     EvaluationResult<SkyValue> evaluationResult = tester.eval(/*keepGoing=*/ true, groupDepA, depC);
@@ -2314,21 +2284,17 @@
     tester
         .getOrCreate(top)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey key, SkyFunction.Environment env)
-                  throws InterruptedException {
-                numTopInvocations.incrementAndGet();
-                if (delayTopSignaling.get()) {
-                  // The graph listener will block on firstKey's signaling of otherTop above until
-                  // this thread starts running.
-                  topRequestedDepOrRestartedBuild.countDown();
-                }
-                // top's builder just requests both deps in a group.
-                env.getValuesOrThrow(
-                    ImmutableList.of(firstKey, slowAddingDep), SomeErrorException.class);
-                return env.valuesMissing() ? null : new StringValue("top");
+            (key, env) -> {
+              numTopInvocations.incrementAndGet();
+              if (delayTopSignaling.get()) {
+                // The graph listener will block on firstKey's signaling of otherTop above until
+                // this thread starts running.
+                topRequestedDepOrRestartedBuild.countDown();
               }
+              // top's builder just requests both deps in a group.
+              env.getValuesOrThrow(
+                  ImmutableList.of(firstKey, slowAddingDep), SomeErrorException.class);
+              return env.valuesMissing() ? null : new StringValue("top");
             });
     // First build : just prime the graph.
     EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
@@ -2408,21 +2374,18 @@
     final CountDownLatch changedKeyCanFinish = new CountDownLatch(1);
     final AtomicBoolean controlTiming = new AtomicBoolean(false);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (!controlTiming.get()) {
-              return;
-            }
-            if (key.equals(midKey) && type == EventType.CHECK_IF_DONE && order == Order.BEFORE) {
-              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                  changedKeyStarted, "changed key didn't start");
-            } else if (key.equals(changedKey)
-                && type == EventType.REMOVE_REVERSE_DEP
-                && order == Order.AFTER
-                && midKey.equals(context)) {
-              changedKeyCanFinish.countDown();
-            }
+        (key, type, order, context) -> {
+          if (!controlTiming.get()) {
+            return;
+          }
+          if (key.equals(midKey) && type == EventType.CHECK_IF_DONE && order == Order.BEFORE) {
+            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                changedKeyStarted, "changed key didn't start");
+          } else if (key.equals(changedKey)
+              && type == EventType.REMOVE_REVERSE_DEP
+              && order == Order.AFTER
+              && midKey.equals(context)) {
+            changedKeyCanFinish.countDown();
           }
         },
         /*deterministic=*/ false);
@@ -2497,16 +2460,7 @@
     tester
         .getOrCreate(restartingKey)
         .setBuilder(
-            new SkyFunction() {
-
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) {
-                if (numFunctionCalls.getAndIncrement() < 2) {
-                  return Restart.SELF;
-                }
-                return expectedValue;
-              }
-            });
+            (skyKey, env) -> numFunctionCalls.getAndIncrement() < 2 ? Restart.SELF : expectedValue);
     assertThat(tester.evalAndGet(/*keepGoing=*/ false, restartingKey)).isEqualTo(expectedValue);
     assertThat(numInconsistencyCalls.get()).isEqualTo(2);
     assertThat(numFunctionCalls.get()).isEqualTo(3);
@@ -2566,26 +2520,23 @@
     tester
         .getOrCreate(restartingKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                numFunctionCalls.getAndIncrement();
-                SkyValue dep1 = env.getValue(alreadyRequestedDep);
-                if (dep1 == null) {
-                  return null;
-                }
-                env.getValues(ImmutableList.of(newlyRequestedDoneDep, newlyRequestedNotDoneDep));
-                if (numFunctionCalls.get() < 4) {
-                  return Restart.SELF;
-                } else if (numFunctionCalls.get() == 4) {
-                  if (cleanBuild.get()) {
-                    Preconditions.checkState(
-                        env.valuesMissing(), "Not done dep should never have been enqueued");
-                  }
-                  return null;
-                }
-                return expectedValue;
+            (skyKey, env) -> {
+              numFunctionCalls.getAndIncrement();
+              SkyValue dep1 = env.getValue(alreadyRequestedDep);
+              if (dep1 == null) {
+                return null;
               }
+              env.getValues(ImmutableList.of(newlyRequestedDoneDep, newlyRequestedNotDoneDep));
+              if (numFunctionCalls.get() < 4) {
+                return Restart.SELF;
+              } else if (numFunctionCalls.get() == 4) {
+                if (cleanBuild.get()) {
+                  Preconditions.checkState(
+                      env.valuesMissing(), "Not done dep should never have been enqueued");
+                }
+                return null;
+              }
+              return expectedValue;
             });
     assertThat(tester.evalAndGet(/*keepGoing=*/ false, restartingKey)).isEqualTo(expectedValue);
     assertThat(numInconsistencyCalls.get()).isEqualTo(2);
@@ -2709,21 +2660,18 @@
     final SkyKey leaf4 = GraphTester.toSkyKey("leaf4");
     final AtomicBoolean shouldNotBuildLeaf4 = new AtomicBoolean(false);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (shouldNotBuildLeaf4.get()
-                && key.equals(leaf4)
-                && type != EventType.REMOVE_REVERSE_DEP
-                && type != EventType.GET_BATCH) {
-              throw new IllegalStateException(
-                  "leaf4 should not have been considered this build: "
-                      + type
-                      + ", "
-                      + order
-                      + ", "
-                      + context);
-            }
+        (key, type, order, context) -> {
+          if (shouldNotBuildLeaf4.get()
+              && key.equals(leaf4)
+              && type != EventType.REMOVE_REVERSE_DEP
+              && type != EventType.GET_BATCH) {
+            throw new IllegalStateException(
+                "leaf4 should not have been considered this build: "
+                    + type
+                    + ", "
+                    + order
+                    + ", "
+                    + context);
           }
         },
         /*deterministic=*/ false);
@@ -2746,31 +2694,26 @@
     tester
         .getOrCreate(topKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                // Request the first group, [leaf0, leaf1, leaf2].
-                // In the first build, it has values ["leaf2", "leaf3", "leaf4"].
-                // In the second build it has values ["leaf2", "leaf3", "leaf5"]
-                Map<SkyKey, SkyValue> values = env.getValues(leaves);
-                if (env.valuesMissing()) {
-                  return null;
-                }
-
-                // Request the second group. In the first build it's [leaf2, leaf4].
-                // In the second build it's [leaf2, leaf5]
-                env.getValues(
-                    ImmutableList.of(
-                        leaves.get(2),
-                        GraphTester.toSkyKey(
-                            ((StringValue) values.get(leaves.get(2))).getValue())));
-                if (env.valuesMissing()) {
-                  return null;
-                }
-
-                return topValue;
+            (skyKey, env) -> {
+              // Request the first group, [leaf0, leaf1, leaf2].
+              // In the first build, it has values ["leaf2", "leaf3", "leaf4"].
+              // In the second build it has values ["leaf2", "leaf3", "leaf5"]
+              Map<SkyKey, SkyValue> values = env.getValues(leaves);
+              if (env.valuesMissing()) {
+                return null;
               }
+
+              // Request the second group. In the first build it's [leaf2, leaf4].
+              // In the second build it's [leaf2, leaf5]
+              env.getValues(
+                  ImmutableList.of(
+                      leaves.get(2),
+                      GraphTester.toSkyKey(((StringValue) values.get(leaves.get(2))).getValue())));
+              if (env.valuesMissing()) {
+                return null;
+              }
+
+              return topValue;
             });
 
     // First build: assert we can evaluate "top".
@@ -2825,38 +2768,35 @@
     // to see if it is changed, and if it is dirty.
     final CountDownLatch threadsStarted = new CountDownLatch(3);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (!blockingEnabled.get()) {
-              return;
-            }
-            if (!key.equals(parent)) {
-              return;
-            }
-            if (type == EventType.IS_CHANGED && order == Order.BEFORE) {
-              threadsStarted.countDown();
-            }
-            // Dirtiness only checked by dirty thread.
-            if (type == EventType.IS_DIRTY && order == Order.BEFORE) {
-              threadsStarted.countDown();
-            }
-            if (type == EventType.MARK_DIRTY) {
-              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                  threadsStarted, "Both threads did not query if value isChanged in time");
-              if (order == Order.BEFORE) {
-                DirtyType dirtyType = (DirtyType) context;
-                if (dirtyType.equals(DirtyType.DIRTY)) {
-                  TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                      waitForChanged, "'changed' thread did not mark value changed in time");
-                  return;
-                }
+        (key, type, order, context) -> {
+          if (!blockingEnabled.get()) {
+            return;
+          }
+          if (!key.equals(parent)) {
+            return;
+          }
+          if (type == EventType.IS_CHANGED && order == Order.BEFORE) {
+            threadsStarted.countDown();
+          }
+          // Dirtiness only checked by dirty thread.
+          if (type == EventType.IS_DIRTY && order == Order.BEFORE) {
+            threadsStarted.countDown();
+          }
+          if (type == EventType.MARK_DIRTY) {
+            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                threadsStarted, "Both threads did not query if value isChanged in time");
+            if (order == Order.BEFORE) {
+              DirtyType dirtyType = (DirtyType) context;
+              if (dirtyType.equals(DirtyType.DIRTY)) {
+                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                    waitForChanged, "'changed' thread did not mark value changed in time");
+                return;
               }
-              if (order == Order.AFTER) {
-                DirtyType dirtyType = ((NotifyingHelper.MarkDirtyAfterContext) context).dirtyType();
-                if (dirtyType.equals(DirtyType.CHANGE)) {
-                  waitForChanged.countDown();
-                }
+            }
+            if (order == Order.AFTER) {
+              DirtyType dirtyType = ((NotifyingHelper.MarkDirtyAfterContext) context).dirtyType();
+              if (dirtyType.equals(DirtyType.CHANGE)) {
+                waitForChanged.countDown();
               }
             }
           }
@@ -3108,18 +3048,14 @@
       tester
           .getOrCreate(leafKey, /*markAsModified=*/ true)
           .setBuilder(
-              new SkyFunction() {
-                @Override
-                public SkyValue compute(SkyKey skyKey, Environment env)
-                    throws InterruptedException {
-                  notifyStart.countDown();
-                  if (shouldSleep.get()) {
-                    // Should be interrupted within 5 seconds.
-                    Thread.sleep(5000);
-                    throw new AssertionError("leaf was not interrupted");
-                  }
-                  return new StringValue("crunchy");
+              (skyKey, env) -> {
+                notifyStart.countDown();
+                if (shouldSleep.get()) {
+                  // Should be interrupted within 5 seconds.
+                  Thread.sleep(5000);
+                  throw new AssertionError("leaf was not interrupted");
                 }
+                return new StringValue("crunchy");
               });
       tester.invalidate();
       TestThread evalThread =
@@ -3289,12 +3225,9 @@
     tester
         .getOrCreate(top)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                topEvaluated.set(true);
-                return env.getValue(leaf) == null ? null : fixedTopValue;
-              }
+            (skyKey, env) -> {
+              topEvaluated.set(true);
+              return env.getValue(leaf) == null ? null : fixedTopValue;
             });
     // And top is evaluated,
     StringValue topValue = (StringValue) tester.evalAndGet("top");
@@ -3337,15 +3270,12 @@
     tester
         .getOrCreate(top)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                topEvaluated.set(true);
+            (skyKey, env) -> {
+              topEvaluated.set(true);
 
-                return env.getValue(other) == null || env.getValue(leaf) == null
-                    ? null
-                    : fixedTopValue;
-              }
+              return env.getValue(other) == null || env.getValue(leaf) == null
+                  ? null
+                  : fixedTopValue;
             });
     // And top is evaluated,
     StringValue topValue = (StringValue) tester.evalAndGet("top");
@@ -3379,27 +3309,23 @@
   public void changedChildChangesDepOfParent() throws Exception {
     SkyKey buildFile = GraphTester.nonHermeticKey("buildFile");
     ValueComputer authorDrink =
-        new ValueComputer() {
-          @Override
-          public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env)
-              throws InterruptedException {
-            String author = ((StringValue) deps.get(buildFile)).getValue();
-            StringValue beverage;
-            switch (author) {
-              case "hemingway":
-                beverage = (StringValue) env.getValue(GraphTester.toSkyKey("absinthe"));
-                break;
-              case "joyce":
-                beverage = (StringValue) env.getValue(GraphTester.toSkyKey("whiskey"));
-                break;
-              default:
-                throw new IllegalStateException(author);
-            }
-            if (beverage == null) {
-              return null;
-            }
-            return new StringValue(author + " drank " + beverage.getValue());
+        (deps, env) -> {
+          String author = ((StringValue) deps.get(buildFile)).getValue();
+          StringValue beverage;
+          switch (author) {
+            case "hemingway":
+              beverage = (StringValue) env.getValue(GraphTester.toSkyKey("absinthe"));
+              break;
+            case "joyce":
+              beverage = (StringValue) env.getValue(GraphTester.toSkyKey("whiskey"));
+              break;
+            default:
+              throw new IllegalStateException(author);
           }
+          if (beverage == null) {
+            return null;
+          }
+          return new StringValue(author + " drank " + beverage.getValue());
         };
 
     tester.set(buildFile, new StringValue("hemingway"));
@@ -3456,13 +3382,8 @@
   }
 
   private static final SkyFunction INTERRUPT_BUILDER =
-      new SkyFunction() {
-
-        @Override
-        public SkyValue compute(SkyKey skyKey, Environment env)
-            throws SkyFunctionException, InterruptedException {
-          throw new InterruptedException();
-        }
+      (skyKey, env) -> {
+        throw new InterruptedException();
       };
 
   /**
@@ -3661,15 +3582,11 @@
     tester.getOrCreate(error).setHasTransientError(true);
     SkyKey topKey = GraphTester.toSkyKey("top");
     SkyFunction errorFunction =
-        new SkyFunction() {
-          @Override
-          public SkyValue compute(SkyKey skyKey, Environment env)
-              throws GenericFunctionException, InterruptedException {
-            try {
-              return env.getValueOrThrow(error, SomeErrorException.class);
-            } catch (SomeErrorException e) {
-              throw new GenericFunctionException(e, Transience.PERSISTENT);
-            }
+        (skyKey, env) -> {
+          try {
+            return env.getValueOrThrow(error, SomeErrorException.class);
+          } catch (SomeErrorException e) {
+            throw new GenericFunctionException(e, Transience.PERSISTENT);
           }
         };
     tester.getOrCreate(topKey).setBuilder(errorFunction);
@@ -3770,17 +3687,13 @@
     tester.getOrCreate(error).setHasError(true);
     SkyKey topKey = GraphTester.toSkyKey("top");
     SkyFunction recoveryErrorFunction =
-        new SkyFunction() {
-          @Override
-          public SkyValue compute(SkyKey skyKey, Environment env)
-              throws SkyFunctionException, InterruptedException {
-            try {
-              env.getValueOrThrow(error, SomeErrorException.class);
-            } catch (SomeErrorException e) {
-              throw new GenericFunctionException(e, Transience.PERSISTENT);
-            }
-            return null;
+        (skyKey, env) -> {
+          try {
+            env.getValueOrThrow(error, SomeErrorException.class);
+          } catch (SomeErrorException e) {
+            throw new GenericFunctionException(e, Transience.PERSISTENT);
           }
+          return null;
         };
     tester.getOrCreate(topKey).setBuilder(recoveryErrorFunction);
     EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
@@ -3853,30 +3766,26 @@
     final CountDownLatch otherThreadWinning = new CountDownLatch(1);
     final AtomicReference<Thread> firstThread = new AtomicReference<>();
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (!waitForSecondCall.get()) {
+        (key, type, order, context) -> {
+          if (!waitForSecondCall.get()) {
+            return;
+          }
+          if (key.equals(midKey)) {
+            if (type == EventType.CREATE_IF_ABSENT) {
+              // The first thread to create midKey will not be the first thread to add a reverse dep
+              // to it.
+              firstThread.compareAndSet(null, Thread.currentThread());
               return;
             }
-            if (key.equals(midKey)) {
-              if (type == EventType.CREATE_IF_ABSENT) {
-                // The first thread to create midKey will not be the first thread to add a
-                // reverse dep to it.
-                firstThread.compareAndSet(null, Thread.currentThread());
-                return;
-              }
-              if (type == EventType.ADD_REVERSE_DEP) {
-                if (order == Order.BEFORE && Thread.currentThread().equals(firstThread.get())) {
-                  // If this thread created midKey, block until the other thread adds a dep on
-                  // it.
-                  TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                      otherThreadWinning, "other thread didn't pass this one");
-                } else if (order == Order.AFTER
-                    && !Thread.currentThread().equals(firstThread.get())) {
-                  // This thread has added a dep. Allow the other thread to proceed.
-                  otherThreadWinning.countDown();
-                }
+            if (type == EventType.ADD_REVERSE_DEP) {
+              if (order == Order.BEFORE && Thread.currentThread().equals(firstThread.get())) {
+                // If this thread created midKey, block until the other thread adds a dep on it.
+                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                    otherThreadWinning, "other thread didn't pass this one");
+              } else if (order == Order.AFTER
+                  && !Thread.currentThread().equals(firstThread.get())) {
+                // This thread has added a dep. Allow the other thread to proceed.
+                otherThreadWinning.countDown();
               }
             }
           }
@@ -3934,58 +3843,48 @@
     tester
         .getOrCreate(errorKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
-                // Given that errorKey waits for otherErrorKey to begin evaluation before completing
-                // its evaluation,
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    otherStarted, "otherErrorKey's SkyFunction didn't start in time.");
-                // And given that errorKey throws an error,
-                throw new GenericFunctionException(
-                    new SomeErrorException("error"), Transience.PERSISTENT);
-              }
+            (skyKey, env) -> {
+              // Given that errorKey waits for otherErrorKey to begin evaluation before completing
+              // its evaluation,
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  otherStarted, "otherErrorKey's SkyFunction didn't start in time.");
+              // And given that errorKey throws an error,
+              throw new GenericFunctionException(
+                  new SomeErrorException("error"), Transience.PERSISTENT);
             });
     tester
         .getOrCreate(otherErrorKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                otherStarted.countDown();
-                int invocations = numOtherInvocations.incrementAndGet();
-                // And given that otherErrorKey waits for errorKey's error to be committed before
-                // trying to get errorKey's value,
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    errorCommitted, "errorKey's error didn't get committed to the graph in time");
-                try {
-                  SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
-                  if (value != null) {
-                    nonNullValueMessage.set("bogus non-null value " + value);
-                  }
-                  if (invocations != 1) {
-                    bogusInvocationMessage.set("bogus invocation count: " + invocations);
-                  }
-                  otherDone.countDown();
-                  // And given that otherErrorKey throws an error,
-                  throw new GenericFunctionException(
-                      new SomeErrorException("other"), Transience.PERSISTENT);
-                } catch (SomeErrorException e) {
-                  fail();
-                  return null;
+            (skyKey, env) -> {
+              otherStarted.countDown();
+              int invocations = numOtherInvocations.incrementAndGet();
+              // And given that otherErrorKey waits for errorKey's error to be committed before
+              // trying to get errorKey's value,
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  errorCommitted, "errorKey's error didn't get committed to the graph in time");
+              try {
+                SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
+                if (value != null) {
+                  nonNullValueMessage.set("bogus non-null value " + value);
                 }
+                if (invocations != 1) {
+                  bogusInvocationMessage.set("bogus invocation count: " + invocations);
+                }
+                otherDone.countDown();
+                // And given that otherErrorKey throws an error,
+                throw new GenericFunctionException(
+                    new SomeErrorException("other"), Transience.PERSISTENT);
+              } catch (SomeErrorException e) {
+                fail();
+                return null;
               }
             });
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (key.equals(errorKey) && type == EventType.SET_VALUE && order == Order.AFTER) {
-              errorCommitted.countDown();
-              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                  otherDone, "otherErrorKey's SkyFunction didn't finish in time.");
-            }
+        (key, type, order, context) -> {
+          if (key.equals(errorKey) && type == EventType.SET_VALUE && order == Order.AFTER) {
+            errorCommitted.countDown();
+            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                otherDone, "otherErrorKey's SkyFunction didn't finish in time.");
           }
         },
         /*deterministic=*/ false);
@@ -4138,16 +4037,13 @@
     tester
         .getOrCreate(wait)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                // Wait for the parent and child actions to complete before computing wait node
-                parentEvaluated.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-                assertThatEvents(eventCollector).containsExactly(childEvent, parentEvent);
+            (skyKey, env) -> {
+              // Wait for the parent and child actions to complete before computing wait node
+              parentEvaluated.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+              assertThatEvents(eventCollector).containsExactly(childEvent, parentEvent);
 
-                env.getListener().handle(Event.progress(waitEvent));
-                return waitStringValue;
-              }
+              env.getListener().handle(Event.progress(waitEvent));
+              return waitStringValue;
             });
     tester
         .getOrCreate(child)
@@ -4773,18 +4669,15 @@
     tester
         .getOrCreate(waitForShutdownKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                shutdownAwaiterStarted.countDown();
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    ((SkyFunctionEnvironment) env).getExceptionLatchForTesting(),
-                    "exception not thrown");
-                // Threadpool is shutting down. Don't try to synchronize anything in the future
-                // during error bubbling.
-                synchronizeThreads.set(false);
-                throw new InterruptedException();
-              }
+            (skyKey, env) -> {
+              shutdownAwaiterStarted.countDown();
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  ((SkyFunctionEnvironment) env).getExceptionLatchForTesting(),
+                  "exception not thrown");
+              // Threadpool is shutting down. Don't try to synchronize anything in the future
+              // during error bubbling.
+              synchronizeThreads.set(false);
+              throw new InterruptedException();
             });
     EvaluationResult<StringValue> result =
         tester.eval(/*keepGoing=*/ false, cachedParentKey, uncachedParentKey, waitForShutdownKey);
@@ -4823,23 +4716,20 @@
     final CountDownLatch topRequestedError = new CountDownLatch(1);
     final CountDownLatch errorMarkedClean = new CountDownLatch(1);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (errorKey.equals(key) && type == EventType.MARK_CLEAN) {
-              if (order == Order.BEFORE) {
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    topRequestedError, "top didn't request");
-              } else {
-                errorMarkedClean.countDown();
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    topSecondEval, "top didn't restart");
-                // Make sure that the other thread notices the error and interrupts this thread.
-                try {
-                  Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
-                } catch (InterruptedException e) {
-                  Thread.currentThread().interrupt();
-                }
+        (key, type, order, context) -> {
+          if (errorKey.equals(key) && type == EventType.MARK_CLEAN) {
+            if (order == Order.BEFORE) {
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  topRequestedError, "top didn't request");
+            } else {
+              errorMarkedClean.countDown();
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  topSecondEval, "top didn't restart");
+              // Make sure that the other thread notices the error and interrupts this thread.
+              try {
+                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
+              } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
               }
             }
           }
@@ -4889,16 +4779,13 @@
     SkyKey errorKey = GraphTester.nonHermeticKey("error");
     final SkyKey otherKey = GraphTester.toSkyKey("other");
     SkyFunction parentBuilder =
-        new SkyFunction() {
-          @Override
-          public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-            env.getValue(errorKey);
-            env.getValue(otherKey);
-            if (env.valuesMissing()) {
-              return null;
-            }
-            return new StringValue("parent");
+        (skyKey, env) -> {
+          env.getValue(errorKey);
+          env.getValue(otherKey);
+          if (env.valuesMissing()) {
+            return null;
           }
+          return new StringValue("parent");
         };
     tester.getOrCreate(parent1Key).setBuilder(parentBuilder);
     tester.getOrCreate(parent2Key).setBuilder(parentBuilder);
@@ -5058,21 +4945,18 @@
     Thread mainThread = Thread.currentThread();
     AtomicBoolean shouldInterrupt = new AtomicBoolean(false);
     injectGraphListenerForTesting(
-        new Listener() {
-          @Override
-          public void accept(SkyKey key, EventType type, Order order, Object context) {
-            if (shouldInterrupt.get()
-                && key.equals(topKey)
-                && type == EventType.IS_READY
-                && order == Order.BEFORE) {
-              mainThread.interrupt();
-              shouldInterrupt.set(false);
-              try {
-                // Make sure threadpool propagates interrupt.
-                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
-              } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-              }
+        (key, type, order, context) -> {
+          if (shouldInterrupt.get()
+              && key.equals(topKey)
+              && type == EventType.IS_READY
+              && order == Order.BEFORE) {
+            mainThread.interrupt();
+            shouldInterrupt.set(false);
+            try {
+              // Make sure threadpool propagates interrupt.
+              Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
+            } catch (InterruptedException e) {
+              Thread.currentThread().interrupt();
             }
           }
         },
diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
index 76e6672..56b4e31 100644
--- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
@@ -40,7 +40,6 @@
 import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor;
 import com.google.devtools.build.lib.concurrent.BlazeInterners;
 import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
 import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
@@ -50,7 +49,6 @@
 import com.google.devtools.build.lib.testutil.TestUtils;
 import com.google.devtools.build.skyframe.GraphTester.StringValue;
 import com.google.devtools.build.skyframe.NotifyingHelper.EventType;
-import com.google.devtools.build.skyframe.NotifyingHelper.Listener;
 import com.google.devtools.build.skyframe.NotifyingHelper.Order;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.testing.junit.testparameterinjector.TestParameter;
@@ -172,18 +170,15 @@
     tester
         .getOrCreate(parentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                SettableFuture<SkyValue> future = SettableFuture.create();
-                future.set(new StringValue("good"));
-                env.dependOnFuture(future);
-                assertThat(env.valuesMissing()).isFalse();
-                try {
-                  return future.get();
-                } catch (ExecutionException e) {
-                  throw new RuntimeException(e);
-                }
+            (skyKey, env) -> {
+              SettableFuture<SkyValue> future = SettableFuture.create();
+              future.set(new StringValue("good"));
+              env.dependOnFuture(future);
+              assertThat(env.valuesMissing()).isFalse();
+              try {
+                return future.get();
+              } catch (ExecutionException e) {
+                throw new RuntimeException(e);
               }
             });
     graph = new InMemoryGraphImpl();
@@ -226,14 +221,11 @@
             });
     graph =
         NotifyingHelper.makeNotifyingTransformer(
-                new Listener() {
-                  @Override
-                  public void accept(SkyKey key, EventType type, Order order, Object context) {
-                    // NodeEntry.addExternalDep is called as part of bookkeeping at the end of
-                    // AbstractParallelEvaluator.Evaluate#run.
-                    if (key == parentKey && type == EventType.ADD_EXTERNAL_DEP) {
-                      doneLatch.countDown();
-                    }
+                (key, type, order, context) -> {
+                  // NodeEntry.addExternalDep is called as part of bookkeeping at the end of
+                  // AbstractParallelEvaluator.Evaluate#run.
+                  if (key == parentKey && type == EventType.ADD_EXTERNAL_DEP) {
+                    doneLatch.countDown();
                   }
                 })
             .transform(new InMemoryGraphImpl());
@@ -286,12 +278,9 @@
             });
     graph =
         NotifyingHelper.makeNotifyingTransformer(
-                new Listener() {
-                  @Override
-                  public void accept(SkyKey key, EventType type, Order order, Object context) {
-                    if (key == childKey && type == EventType.SET_VALUE) {
-                      doneLatch.countDown();
-                    }
+                (key, type, order, context) -> {
+                  if (key == childKey && type == EventType.SET_VALUE) {
+                    doneLatch.countDown();
                   }
                 })
             .transform(new InMemoryGraphImpl());
@@ -305,27 +294,21 @@
    */
   @Test
   public void interruptedFunction() throws Exception {
-    runInterruptionTest(new SkyFunctionFactory() {
-      @Override
-      public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) {
-        return new SkyFunction() {
-          @Override
-          public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
-            // Signal the waiting test thread that the evaluator thread has really started.
-            threadStarted.release();
+    runInterruptionTest(
+        (threadStarted, errorMessage) ->
+            (key, env) -> {
+              // Signal the waiting test thread that the evaluator thread has really started.
+              threadStarted.release();
 
-            // Simulate a SkyFunction that runs for 10 seconds (this number was chosen arbitrarily).
-            // The main thread should interrupt it shortly after it got started.
-            Thread.sleep(10 * 1000);
+              // Simulate a SkyFunction that runs for 10 seconds (this number was chosen
+              // arbitrarily). The main thread should interrupt it shortly after it got started.
+              Thread.sleep(10 * 1000);
 
-            // Set an error message to indicate that the expected interruption didn't happen.
-            // We can't use Assert.fail(String) on an async thread.
-            errorMessage[0] = "SkyFunction should have been interrupted";
-            return null;
-          }
-        };
-      }
-    });
+              // Set an error message to indicate that the expected interruption didn't happen.
+              // We can't use Assert.fail(String) on an async thread.
+              errorMessage[0] = "SkyFunction should have been interrupted";
+              return null;
+            });
   }
 
   /**
@@ -338,10 +321,8 @@
   @Test
   public void interruptedEvaluatorThread() throws Exception {
     runInterruptionTest(
-        new SkyFunctionFactory() {
-          @Override
-          public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) {
-            return new SkyFunction() {
+        (threadStarted, errorMessage) ->
+            new SkyFunction() {
               // No need to synchronize access to this field; we always request just one more
               // dependency, so it's only one SkyFunction running at any time.
               private int valueIdCounter = 0;
@@ -360,9 +341,7 @@
                 // SkyFunctions.
                 return null;
               }
-            };
-          }
-        });
+            });
   }
 
   @Test
@@ -406,19 +385,19 @@
     };
     // And A's SkyFunction tries to observe an interrupt after it starts computing,
     AtomicBoolean keyAComputeInterrupted = new AtomicBoolean(false);
-    tester.getOrCreate(keyA).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-        keyAStartedComputingLatch.countDown();
-        try {
-          Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
-          throw new IllegalStateException("shouldn't get here");
-        } catch (InterruptedException e) {
-          keyAComputeInterrupted.set(true);
-          throw e;
-        }
-      }
-    });
+    tester
+        .getOrCreate(keyA)
+        .setBuilder(
+            (skyKey, env) -> {
+              keyAStartedComputingLatch.countDown();
+              try {
+                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
+                throw new IllegalStateException("shouldn't get here");
+              } catch (InterruptedException e) {
+                keyAComputeInterrupted.set(true);
+                throw e;
+              }
+            });
 
     // And we have a dedicated thread that kicks off the evaluation of A and B together (in that
     // order).
@@ -453,14 +432,14 @@
     final SkyKey waitKey = GraphTester.toSkyKey("wait");
     final SkyKey fastKey = GraphTester.toSkyKey("fast");
     SkyKey leafKey = GraphTester.toSkyKey("leaf");
-    tester.getOrCreate(waitKey).setBuilder(new SkyFunction() {
-          @Override
-          public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-            allValuesReady.countDown();
-            Thread.sleep(10000);
-            throw new AssertionError("Should have been interrupted");
-          }
-        });
+    tester
+        .getOrCreate(waitKey)
+        .setBuilder(
+            (skyKey, env) -> {
+              allValuesReady.countDown();
+              Thread.sleep(10000);
+              throw new AssertionError("Should have been interrupted");
+            });
     tester.getOrCreate(fastKey).setBuilder(new ChainedFunction(null, null, allValuesReady, false,
         new StringValue("fast"), ImmutableList.of(leafKey)));
     tester.set(leafKey, new StringValue("leaf"));
@@ -547,23 +526,22 @@
                 GraphTester.NODE_TYPE, valueBuilderFactory.create(threadStarted, wasError)),
             false);
 
-    Thread t = new Thread(new Runnable() {
-        @Override
-        public void run() {
-          try {
-            evaluator.eval(ImmutableList.of(GraphTester.toSkyKey("a")));
+    Thread t =
+        new Thread(
+            () -> {
+              try {
+                evaluator.eval(ImmutableList.of(GraphTester.toSkyKey("a")));
 
-            // There's no real need to set an error here. If the thread is not interrupted then
-            // threadInterrupted is not released and the test thread will fail to acquire it.
-            wasError[0] = "evaluation should have been interrupted";
-          } catch (InterruptedException e) {
-            // This is the interrupt we are waiting for. It should come straight from the
-            // evaluator (more precisely, the AbstractQueueVisitor).
-            // Signal the waiting test thread that the interrupt was acknowledged.
-            threadInterrupted.release();
-          }
-        }
-    });
+                // There's no real need to set an error here. If the thread is not interrupted then
+                // threadInterrupted is not released and the test thread will fail to acquire it.
+                wasError[0] = "evaluation should have been interrupted";
+              } catch (InterruptedException e) {
+                // This is the interrupt we are waiting for. It should come straight from the
+                // evaluator (more precisely, the AbstractQueueVisitor).
+                // Signal the waiting test thread that the interrupt was acknowledged.
+                threadInterrupted.release();
+              }
+            });
 
     // Start the thread and wait for a semaphore. This ensures that the thread was really started.
     t.start();
@@ -671,15 +649,14 @@
     set("a", "a").setWarning("warning on 'a'");
     SkyKey a = GraphTester.toSkyKey("a");
     SkyKey top = GraphTester.toSkyKey("top");
-    tester.getOrCreate(top).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey key, Environment env)
-          throws SkyFunctionException, InterruptedException {
-        // The event from a should already have been posted.
-        assertThat(storedEventHandler.getEvents()).hasSize(1);
-        return new StringValue("foo");
-      }
-    });
+    tester
+        .getOrCreate(top)
+        .setBuilder(
+            (key, env) -> {
+              // The event from a should already have been posted.
+              assertThat(storedEventHandler.getEvents()).hasSize(1);
+              return new StringValue("foo");
+            });
     // Build a so that it is already in the graph.
     eval(false, a);
     storedEventHandler.clear();
@@ -696,21 +673,21 @@
     SkyKey b = GraphTester.toSkyKey("b");
     tester.getOrCreate(b).setHasError(true);
     Event errorEvent = Event.error("foobar");
-    tester.getOrCreate(a).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey key, Environment env)
-          throws SkyFunctionException, InterruptedException {
-        try {
-          if (env.getValueOrThrow(b, SomeErrorException.class) == null) {
-            return null;
-          }
-        } catch (SomeErrorException ignored) {
-          // Continue silently.
-        }
-        env.getListener().handle(errorEvent);
-        throw new SkyFunctionException(new SomeErrorException("bazbar"), Transience.PERSISTENT) {};
-      }
-    });
+    tester
+        .getOrCreate(a)
+        .setBuilder(
+            (key, env) -> {
+              try {
+                if (env.getValueOrThrow(b, SomeErrorException.class) == null) {
+                  return null;
+                }
+              } catch (SomeErrorException ignored) {
+                // Continue silently.
+              }
+              env.getListener().handle(errorEvent);
+              throw new SkyFunctionException(
+                  new SomeErrorException("bazbar"), Transience.PERSISTENT) {};
+            });
     eval(false, a);
     assertThat(storedEventHandler.getEvents()).containsExactly(errorEvent);
   }
@@ -1841,12 +1818,12 @@
     graph = new InMemoryGraphImpl();
     SkyKey errorKey = GraphTester.toSkyKey("my_error_value");
     final SomeOtherErrorException exception = new SomeOtherErrorException("error exception");
-    tester.getOrCreate(errorKey).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
-        throw new SkyFunctionException(exception, Transience.PERSISTENT) {};
-      }
-    });
+    tester
+        .getOrCreate(errorKey)
+        .setBuilder(
+            (skyKey, env) -> {
+              throw new SkyFunctionException(exception, Transience.PERSISTENT) {};
+            });
     SkyKey topKey = GraphTester.toSkyKey("top");
     tester.getOrCreate(topKey).addErrorDependency(errorKey, new StringValue("recovered"))
         .setComputedValue(CONCATENATE);
@@ -1875,34 +1852,30 @@
     final SomeErrorException exception = new SomeErrorException("error exception");
     final SomeErrorException topException = new SomeErrorException("top exception");
     final StringValue topValue = new StringValue("top");
-    tester.getOrCreate(errorKey).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) throws GenericFunctionException {
-        throw new GenericFunctionException(exception, Transience.PERSISTENT);
-      }
-    });
+    tester
+        .getOrCreate(errorKey)
+        .setBuilder(
+            (skyKey, env) -> {
+              throw new GenericFunctionException(exception, Transience.PERSISTENT);
+            });
     SkyKey topKey = GraphTester.toSkyKey("top");
     final SkyKey parentKey = GraphTester.toSkyKey("parent");
     tester.getOrCreate(parentKey).addDependency(errorKey).setComputedValue(CONCATENATE);
     tester
         .getOrCreate(topKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws GenericFunctionException, InterruptedException {
-                try {
-                  if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) {
-                    return null;
-                  }
-                } catch (SomeErrorException e) {
-                  assertWithMessage(e.toString()).that(e).isEqualTo(exception);
+            (skyKey, env) -> {
+              try {
+                if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) {
+                  return null;
                 }
-                if (keepGoing) {
-                  return topValue;
-                } else {
-                  throw new GenericFunctionException(topException, Transience.PERSISTENT);
-                }
+              } catch (SomeErrorException e) {
+                assertWithMessage(e.toString()).that(e).isEqualTo(exception);
+              }
+              if (keepGoing) {
+                return topValue;
+              } else {
+                throw new GenericFunctionException(topException, Transience.PERSISTENT);
               }
             });
     tester.getOrCreate(topKey).addErrorDependency(errorKey, new StringValue("recovered"))
@@ -1946,32 +1919,31 @@
     }
     final SkyKey leaf4 = GraphTester.toSkyKey("leaf4");
     tester.set(leaf4, new StringValue("leaf" + 4));
-    tester.getOrCreate(topKey).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException,
-          InterruptedException {
-        if (valuesOrThrow) {
-          env.getValuesOrThrow(leaves, SomeErrorException.class);
-        } else {
-          env.getValues(leaves);
-        }
-        if (twoCalls && env.valuesMissing()) {
-          return null;
-        }
-        SkyKey first = sameFirst ? leaves.get(0) : leaf4;
-        SkyKey second = sameFirst ? leaf4 : leaves.get(2);
-        List<SkyKey> secondRequest = ImmutableList.of(first, second);
-        if (valuesOrThrow) {
-          env.getValuesOrThrow(secondRequest, SomeErrorException.class);
-        } else {
-          env.getValues(secondRequest);
-        }
-        if (env.valuesMissing()) {
-          return null;
-        }
-        return new StringValue("top");
-      }
-    });
+    tester
+        .getOrCreate(topKey)
+        .setBuilder(
+            (skyKey, env) -> {
+              if (valuesOrThrow) {
+                env.getValuesOrThrow(leaves, SomeErrorException.class);
+              } else {
+                env.getValues(leaves);
+              }
+              if (twoCalls && env.valuesMissing()) {
+                return null;
+              }
+              SkyKey first = sameFirst ? leaves.get(0) : leaf4;
+              SkyKey second = sameFirst ? leaf4 : leaves.get(2);
+              ImmutableList<SkyKey> secondRequest = ImmutableList.of(first, second);
+              if (valuesOrThrow) {
+                env.getValuesOrThrow(secondRequest, SomeErrorException.class);
+              } else {
+                env.getValues(secondRequest);
+              }
+              if (env.valuesMissing()) {
+                return null;
+              }
+              return new StringValue("top");
+            });
     eval(/*keepGoing=*/false, topKey);
     assertThat(eval(/*keepGoing=*/false, topKey)).isEqualTo(new StringValue("top"));
   }
@@ -2021,12 +1993,12 @@
     SkyKey parentKey = GraphTester.toSkyKey("parent");
     final SkyKey errorDep = GraphTester.toSkyKey("errorChild");
     final SomeErrorException childExn = new SomeErrorException("child error");
-    tester.getOrCreate(errorDep).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
-        throw new GenericFunctionException(childExn, Transience.PERSISTENT);
-      }
-    });
+    tester
+        .getOrCreate(errorDep)
+        .setBuilder(
+            (skyKey, env) -> {
+              throw new GenericFunctionException(childExn, Transience.PERSISTENT);
+            });
     final List<SkyKey> deps = new ArrayList<>();
     for (int i = 1; i <= 3; i++) {
       SkyKey dep = GraphTester.toSkyKey("child" + i);
@@ -2037,24 +2009,20 @@
     tester
         .getOrCreate(parentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                try {
-                  SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class);
-                  if (value == null) {
-                    return null;
-                  }
-                } catch (SomeErrorException e) {
-                  // Recover from the child error.
-                }
-                env.getValues(deps);
-                if (env.valuesMissing()) {
+            (skyKey, env) -> {
+              try {
+                SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class);
+                if (value == null) {
                   return null;
                 }
-                throw new GenericFunctionException(parentExn, Transience.PERSISTENT);
+              } catch (SomeErrorException e) {
+                // Recover from the child error.
               }
+              env.getValues(deps);
+              if (env.valuesMissing()) {
+                return null;
+              }
+              throw new GenericFunctionException(parentExn, Transience.PERSISTENT);
             });
     EvaluationResult<StringValue> evaluationResult = eval(keepGoing, ImmutableList.of(parentKey));
     assertThat(evaluationResult.hasError()).isTrue();
@@ -2129,11 +2097,8 @@
     ExtendedEventHandler reporter =
         new Reporter(
             new EventBus(),
-            new EventHandler() {
-              @Override
-              public void handle(Event e) {
-                throw new IllegalStateException();
-              }
+            e -> {
+              throw new IllegalStateException();
             });
 
     MemoizingEvaluator aug =
@@ -2191,46 +2156,41 @@
     tester
         .getOrCreate(parentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                int invocations = numParentInvocations.incrementAndGet();
-                if (handleChildError) {
-                  try {
-                    SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class);
-                    // On the first invocation, either the child error should already be cached and
-                    // not propagated, or it should be computed freshly and not propagated. On the
-                    // second build (error bubbling), the child error should be propagated.
-                    assertWithMessage("bogus non-null value " + value).that(value == null).isTrue();
-                    assertWithMessage("parent incorrectly re-computed during normal evaluation")
-                        .that(invocations)
-                        .isEqualTo(1);
-                    assertWithMessage("child error not propagated during error bubbling")
-                        .that(env.inErrorBubblingForTesting())
-                        .isFalse();
-                    return value;
-                  } catch (SomeErrorException e) {
-                    assertWithMessage("child error propagated during normal evaluation")
-                        .that(env.inErrorBubblingForTesting())
-                        .isTrue();
-                    assertThat(invocations).isEqualTo(2);
-                    return null;
-                  }
+            (skyKey, env) -> {
+              int invocations = numParentInvocations.incrementAndGet();
+              if (handleChildError) {
+                try {
+                  SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class);
+                  // On the first invocation, either the child error should already be cached and
+                  // not propagated, or it should be computed freshly and not propagated. On the
+                  // second build (error bubbling), the child error should be propagated.
+                  assertWithMessage("bogus non-null value " + value).that(value == null).isTrue();
+                  assertWithMessage("parent incorrectly re-computed during normal evaluation")
+                      .that(invocations)
+                      .isEqualTo(1);
+                  assertWithMessage("child error not propagated during error bubbling")
+                      .that(env.inErrorBubblingForTesting())
+                      .isFalse();
+                  return value;
+                } catch (SomeErrorException e) {
+                  assertWithMessage("child error propagated during normal evaluation")
+                      .that(env.inErrorBubblingForTesting())
+                      .isTrue();
+                  assertThat(invocations).isEqualTo(2);
+                  return null;
+                }
+              } else {
+                if (invocations == 1) {
+                  assertWithMessage("parent's first computation should be during normal evaluation")
+                      .that(env.inErrorBubblingForTesting())
+                      .isFalse();
+                  return env.getValue(childKey);
                 } else {
-                  if (invocations == 1) {
-                    assertWithMessage(
-                            "parent's first computation should be during normal evaluation")
-                        .that(env.inErrorBubblingForTesting())
-                        .isFalse();
-                    return env.getValue(childKey);
-                  } else {
-                    assertThat(invocations).isEqualTo(2);
-                    assertWithMessage("parent incorrectly re-computed during normal evaluation")
-                        .that(env.inErrorBubblingForTesting())
-                        .isTrue();
-                    return env.getValue(childKey);
-                  }
+                  assertThat(invocations).isEqualTo(2);
+                  assertWithMessage("parent incorrectly re-computed during normal evaluation")
+                      .that(env.inErrorBubblingForTesting())
+                      .isTrue();
+                  return env.getValue(childKey);
                 }
               }
             });
@@ -2284,64 +2244,52 @@
     tester
         .getOrCreate(otherParentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                int invocations = numOtherParentInvocations.incrementAndGet();
-                assertWithMessage("otherParentKey should not be restarted")
-                    .that(invocations)
-                    .isEqualTo(1);
-                return env.getValue(otherKey);
-              }
+            (skyKey, env) -> {
+              int invocations = numOtherParentInvocations.incrementAndGet();
+              assertWithMessage("otherParentKey should not be restarted")
+                  .that(invocations)
+                  .isEqualTo(1);
+              return env.getValue(otherKey);
             });
     tester
         .getOrCreate(otherKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
-                otherStarted.countDown();
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    errorCommitted, "error didn't get committed to the graph in time");
-                return new StringValue("other");
-              }
+            (skyKey, env) -> {
+              otherStarted.countDown();
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  errorCommitted, "error didn't get committed to the graph in time");
+              return new StringValue("other");
             });
     tester
         .getOrCreate(errorKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
-                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
-                    otherStarted, "other didn't start in time");
-                throw new GenericFunctionException(
-                    new SomeErrorException("error"), Transience.PERSISTENT);
-              }
+            (skyKey, env) -> {
+              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
+                  otherStarted, "other didn't start in time");
+              throw new GenericFunctionException(
+                  new SomeErrorException("error"), Transience.PERSISTENT);
             });
     tester
         .getOrCreate(errorParentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                int invocations = numErrorParentInvocations.incrementAndGet();
-                try {
-                  SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
-                  assertWithMessage("bogus non-null value " + value).that(value == null).isTrue();
-                  if (invocations == 1) {
-                    return null;
-                  } else {
-                    assertThat(env.inErrorBubblingForTesting()).isFalse();
-                    fail("RACE CONDITION: errorParentKey was restarted!");
-                    return null;
-                  }
-                } catch (SomeErrorException e) {
-                  assertWithMessage("child error propagated during normal evaluation")
-                      .that(env.inErrorBubblingForTesting())
-                      .isTrue();
-                  assertThat(invocations).isEqualTo(2);
+            (skyKey, env) -> {
+              int invocations = numErrorParentInvocations.incrementAndGet();
+              try {
+                SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
+                assertWithMessage("bogus non-null value " + value).that(value == null).isTrue();
+                if (invocations == 1) {
+                  return null;
+                } else {
+                  assertThat(env.inErrorBubblingForTesting()).isFalse();
+                  fail("RACE CONDITION: errorParentKey was restarted!");
                   return null;
                 }
+              } catch (SomeErrorException e) {
+                assertWithMessage("child error propagated during normal evaluation")
+                    .that(env.inErrorBubblingForTesting())
+                    .isTrue();
+                assertThat(invocations).isEqualTo(2);
+                return null;
               }
             });
     graph =
@@ -2398,15 +2346,15 @@
     EvaluationResult<StringValue> result = eval(/*keepGoing=*/true, ImmutableList.of(errorKey));
     assertThatEvaluationResult(result).hasSingletonErrorThat(errorKey);
     SkyKey rogueKey = GraphTester.toSkyKey("rogue");
-    tester.getOrCreate(rogueKey).setBuilder(new SkyFunction() {
-      @Override
-      public SkyValue compute(SkyKey skyKey, Environment env) {
-        // This SkyFunction could do an arbitrarily bad computation, e.g. loop-forever. So we want
-        // to make sure that it is never run when we want to fail-fast anyway.
-        fail("eval call should have already terminated");
-        return null;
-      }
-    });
+    tester
+        .getOrCreate(rogueKey)
+        .setBuilder(
+            (skyKey, env) -> {
+              // This SkyFunction could do an arbitrarily bad computation, e.g. loop-forever. So we
+              // want to make sure that it is never run when we want to fail-fast anyway.
+              fail("eval call should have already terminated");
+              return null;
+            });
     result = eval(/*keepGoing=*/false, ImmutableList.of(errorKey, rogueKey));
     assertThatEvaluationResult(result).hasErrorMapThat().hasSize(1);
     assertThatEvaluationResult(result).hasErrorEntryForKeyThat(errorKey);
@@ -2436,23 +2384,20 @@
     tester
         .getOrCreate(parentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
-                switch (numComputes.incrementAndGet()) {
-                  case 1:
-                    env.getValue(child1Key);
-                    Preconditions.checkState(env.valuesMissing());
-                    return null;
-                  case 2:
-                    env.getValue(child2Key);
-                    Preconditions.checkState(env.valuesMissing());
-                    return null;
-                  case 3:
-                    return new StringValue("the third time's the charm!");
-                  default:
-                    throw new IllegalStateException();
-                }
+            (skyKey, env) -> {
+              switch (numComputes.incrementAndGet()) {
+                case 1:
+                  env.getValue(child1Key);
+                  Preconditions.checkState(env.valuesMissing());
+                  return null;
+                case 2:
+                  env.getValue(child2Key);
+                  Preconditions.checkState(env.valuesMissing());
+                  return null;
+                case 3:
+                  return new StringValue("the third time's the charm!");
+                default:
+                  throw new IllegalStateException();
               }
             });
     EvaluationResult<StringValue> result = eval(/*keepGoing=*/ false, ImmutableList.of(parentKey));
@@ -2473,34 +2418,26 @@
     tester
         .getOrCreate(grandparentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                try {
-                  return env.getValueOrThrow(parentKey, SomeErrorException.class);
-                } catch (SomeErrorException e) {
-                  errorPropagated.set(true);
-                  throw new GenericFunctionException(e, Transience.PERSISTENT);
-                }
+            (skyKey, env) -> {
+              try {
+                return env.getValueOrThrow(parentKey, SomeErrorException.class);
+              } catch (SomeErrorException e) {
+                errorPropagated.set(true);
+                throw new GenericFunctionException(e, Transience.PERSISTENT);
               }
             });
     tester
         .getOrCreate(parentKey)
         .setBuilder(
-            new SkyFunction() {
-              @Override
-              public SkyValue compute(SkyKey skyKey, Environment env)
-                  throws SkyFunctionException, InterruptedException {
-                if (explicitlyPropagateError) {
-                  try {
-                    return env.getValueOrThrow(childKey, SomeErrorException.class);
-                  } catch (SomeErrorException e) {
-                    throw new GenericFunctionException(e);
-                  }
-                } else {
-                  return env.getValue(childKey);
+            (skyKey, env) -> {
+              if (explicitlyPropagateError) {
+                try {
+                  return env.getValueOrThrow(childKey, SomeErrorException.class);
+                } catch (SomeErrorException e) {
+                  throw new GenericFunctionException(e);
                 }
+              } else {
+                return env.getValue(childKey);
               }
             });
     tester.getOrCreate(childKey).setHasError(/*hasError=*/true);