Update from Google.

--
MOE_MIGRATED_REVID=85702957
diff --git a/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java b/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java
new file mode 100644
index 0000000..956e404
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java
@@ -0,0 +1,209 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+package com.google.devtools.build.skyframe;
+
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+/**
+ * Encapsulation of data stored by {@link NodeEntry} when the value has finished building.
+ *
+ * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
+ */
+public abstract class ValueWithMetadata implements SkyValue {
+  protected final SkyValue value;
+
+  private static final NestedSet<TaggedEvents> NO_EVENTS =
+      NestedSetBuilder.<TaggedEvents>emptySet(Order.STABLE_ORDER);
+
+  public ValueWithMetadata(SkyValue value) {
+    this.value = value;
+  }
+
+  /** Builds a value entry value that has an error (and no value value).
+   *
+   * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
+   */
+  public static ValueWithMetadata error(ErrorInfo errorInfo,
+      NestedSet<TaggedEvents> transitiveEvents) {
+    return new ErrorInfoValue(errorInfo, null, transitiveEvents);
+  }
+
+  /**
+   * Builds a value entry value that has a value value, and possibly an error (constructed from its
+   * children's errors).
+   *
+   * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
+   */
+  static SkyValue normal(@Nullable SkyValue value, @Nullable ErrorInfo errorInfo,
+      NestedSet<TaggedEvents> transitiveEvents) {
+    Preconditions.checkState(value != null || errorInfo != null,
+        "Value and error cannot both be null");
+    if (errorInfo == null) {
+      return transitiveEvents.isEmpty()
+          ? value
+          : new ValueWithEvents(value, transitiveEvents);
+    }
+    return new ErrorInfoValue(errorInfo, value, transitiveEvents);
+  }
+
+
+  @Nullable SkyValue getValue() {
+    return value;
+  }
+
+  @Nullable
+  abstract ErrorInfo getErrorInfo();
+
+  abstract NestedSet<TaggedEvents> getTransitiveEvents();
+
+  static final class ValueWithEvents extends ValueWithMetadata {
+
+    private final NestedSet<TaggedEvents> transitiveEvents;
+
+    ValueWithEvents(SkyValue value, NestedSet<TaggedEvents> transitiveEvents) {
+      super(Preconditions.checkNotNull(value));
+      this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
+    }
+
+    @Nullable
+    @Override
+    ErrorInfo getErrorInfo() { return null; }
+
+    @Override
+    NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
+
+    /**
+     * We override equals so that if the same value is written to a {@link NodeEntry} twice, it can
+     * verify that the two values are equal, and avoid incrementing its version.
+     */
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+
+      ValueWithEvents that = (ValueWithEvents) o;
+
+      // Shallow equals is a middle ground between using default equals, which might miss
+      // nested sets with the same elements, and deep equality checking, which would be expensive.
+      // All three choices are sound, since shallow equals and default equals are more
+      // conservative than deep equals. Using shallow equals means that we may unnecessarily
+      // consider some values unequal that are actually equal, but this is still a net win over
+      // deep equals.
+      return value.equals(that.value) && transitiveEvents.shallowEquals(that.transitiveEvents);
+    }
+
+    @Override
+    public int hashCode() {
+      return 31 * value.hashCode() + transitiveEvents.hashCode();
+    }
+
+    @Override
+    public String toString() { return value.toString(); }
+  }
+
+  static final class ErrorInfoValue extends ValueWithMetadata {
+
+    private final ErrorInfo errorInfo;
+    private final NestedSet<TaggedEvents> transitiveEvents;
+
+    ErrorInfoValue(ErrorInfo errorInfo, @Nullable SkyValue value,
+        NestedSet<TaggedEvents> transitiveEvents) {
+      super(value);
+      this.errorInfo = Preconditions.checkNotNull(errorInfo);
+      this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
+    }
+
+    @Nullable
+    @Override
+    ErrorInfo getErrorInfo() { return errorInfo; }
+
+    @Override
+    NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+
+      ErrorInfoValue that = (ErrorInfoValue) o;
+
+      // Shallow equals is a middle ground between using default equals, which might miss
+      // nested sets with the same elements, and deep equality checking, which would be expensive.
+      // All three choices are sound, since shallow equals and default equals are more
+      // conservative than deep equals. Using shallow equals means that we may unnecessarily
+      // consider some values unequal that are actually equal, but this is still a net win over
+      // deep equals.
+      return Objects.equals(this.value, that.value)
+          && Objects.equals(this.errorInfo, that.errorInfo)
+          && transitiveEvents.shallowEquals(that.transitiveEvents);
+    }
+
+    @Override
+    public int hashCode() {
+      return 31 * Objects.hash(value, errorInfo) + transitiveEvents.shallowHashCode();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder result = new StringBuilder();
+      if (value != null) {
+        result.append("Value: ").append(value);
+      }
+      if (errorInfo != null) {
+        if (result.length() > 0) {
+          result.append("; ");
+        }
+        result.append("Error: ").append(errorInfo);
+      }
+      return result.toString();
+    }
+  }
+
+  static SkyValue justValue(SkyValue value) {
+    if (value instanceof ValueWithMetadata) {
+      return ((ValueWithMetadata) value).getValue();
+    }
+    return value;
+  }
+
+  static ValueWithMetadata wrapWithMetadata(SkyValue value) {
+    if (value instanceof ValueWithMetadata) {
+      return (ValueWithMetadata) value;
+    }
+    return new ValueWithEvents(value, NO_EVENTS);
+  }
+
+  @Nullable
+  public static ErrorInfo getMaybeErrorInfo(SkyValue value) {
+    if (value.getClass() == ErrorInfoValue.class) {
+      return ((ValueWithMetadata) value).getErrorInfo();
+    }
+    return null;
+
+  }
+}
\ No newline at end of file