Update from Google.

--
MOE_MIGRATED_REVID=85702957
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
new file mode 100644
index 0000000..9fc3df4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -0,0 +1,578 @@
+// 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
+// limitations under the License.
+package com.google.devtools.build.lib.skyframe;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ListMultimap;
+import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.DependencyResolver.Dependency;
+import com.google.devtools.build.lib.analysis.LabelAndConfiguration;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
+import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.StoredEventHandler;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.InputFile;
+import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
+import com.google.devtools.build.lib.packages.NoSuchThingException;
+import com.google.devtools.build.lib.packages.PackageGroup;
+import com.google.devtools.build.lib.packages.RawAttributeMapper;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.packages.TargetUtils;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.skyframe.AspectFunction.AspectCreationException;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutor.BuildViewProvider;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import com.google.devtools.build.skyframe.ValueOrException2;
+import com.google.devtools.build.skyframe.ValueOrException3;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/**
+ * SkyFunction for {@link ConfiguredTargetValue}s.
+ */
+final class ConfiguredTargetFunction implements SkyFunction {
+
+  /**
+   * Exception class that signals an error during the evaluation of a dependency.
+   */
+  public static class DependencyEvaluationException extends Exception {
+    private final SkyKey rootCauseSkyKey;
+
+    public DependencyEvaluationException(Exception cause) {
+      super(cause);
+      this.rootCauseSkyKey = null;
+    }
+
+    public DependencyEvaluationException(SkyKey rootCauseSkyKey, Exception cause) {
+      super(cause);
+      this.rootCauseSkyKey = rootCauseSkyKey;
+    }
+
+    /**
+     * Returns the key of the root cause or null if the problem was with this target.
+     */
+    public SkyKey getRootCauseSkyKey() {
+      return rootCauseSkyKey;
+    }
+
+    @Override
+    public Exception getCause() {
+      return (Exception) super.getCause();
+    }
+  }
+
+  private static final Function<Dependency, SkyKey> TO_KEYS =
+      new Function<Dependency, SkyKey>() {
+    @Override
+    public SkyKey apply(Dependency input) {
+      return ConfiguredTargetValue.key(input.getLabel(), input.getConfiguration());
+    }
+  };
+
+  private final BuildViewProvider buildViewProvider;
+
+  ConfiguredTargetFunction(BuildViewProvider buildViewProvider) {
+    this.buildViewProvider = buildViewProvider;
+  }
+
+  @Override
+  public SkyValue compute(SkyKey key, Environment env) throws ConfiguredTargetFunctionException,
+      InterruptedException {
+    SkyframeBuildView view = buildViewProvider.getSkyframeBuildView();
+
+    ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument();
+    LabelAndConfiguration lc = LabelAndConfiguration.of(
+        configuredTargetKey.getLabel(), configuredTargetKey.getConfiguration());
+
+    BuildConfiguration configuration = lc.getConfiguration();
+
+    PackageValue packageValue =
+        (PackageValue) env.getValue(PackageValue.key(lc.getLabel().getPackageIdentifier()));
+    if (packageValue == null) {
+      return null;
+    }
+
+    Target target;
+    try {
+      target = packageValue.getPackage().getTarget(lc.getLabel().getName());
+    } catch (NoSuchTargetException e1) {
+      throw new ConfiguredTargetFunctionException(new NoSuchTargetException(lc.getLabel(),
+          "No such target"));
+    }
+    // TODO(bazel-team): This is problematic - we create the right key, but then end up with a value
+    // that doesn't match; we can even have the same value multiple times. However, I think it's
+    // only triggered in tests (i.e., in normal operation, the configuration passed in is already
+    // null).
+    if (target instanceof InputFile) {
+      // InputFileConfiguredTarget expects its configuration to be null since it's not used.
+      configuration = null;
+    } else if (target instanceof PackageGroup) {
+      // Same for PackageGroupConfiguredTarget.
+      configuration = null;
+    }
+    TargetAndConfiguration ctgValue =
+        new TargetAndConfiguration(target, configuration);
+
+    SkyframeDependencyResolver resolver = view.createDependencyResolver(env);
+    if (resolver == null) {
+      return null;
+    }
+
+    try {
+      // Get the configuration targets that trigger this rule's configurable attributes.
+      Set<ConfigMatchingProvider> configConditions =
+          getConfigConditions(ctgValue.getTarget(), env, resolver, ctgValue);
+      if (configConditions == null) {
+        // Those targets haven't yet been resolved.
+        return null;
+      }
+
+      ListMultimap<Attribute, ConfiguredTarget> depValueMap =
+          computeDependencies(env, resolver, ctgValue, null, configConditions);
+      return createConfiguredTarget(
+          view, env, target, configuration, depValueMap, configConditions);
+    } catch (DependencyEvaluationException e) {
+      throw new ConfiguredTargetFunctionException(e.getRootCauseSkyKey(), e.getCause());
+    }
+  }
+
+  /**
+   * Computes the direct dependencies of a node in the configured target graph (a configured
+   * target or an aspect).
+   *
+   * <p>Returns null if Skyframe hasn't evaluated the required dependencies yet. In this case, the
+   * caller should also return null to Skyframe.
+   *
+   * @param env the Skyframe environment
+   * @param resolver The dependency resolver
+   * @param ctgValue The label and the configuration of the node
+   * @param aspectDefinition the aspect of the node (if null, the node is a configured target,
+   *     otherwise it's an asect)
+   * @param configConditions the configuration conditions for evaluating the attributes of the node
+   * @return an attribute -&gt; direct dependency multimap
+   * @throws ConfiguredTargetFunctionException
+   */
+  @Nullable
+  static ListMultimap<Attribute, ConfiguredTarget> computeDependencies(
+      Environment env, SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue,
+      AspectDefinition aspectDefinition, Set<ConfigMatchingProvider> configConditions)
+      throws DependencyEvaluationException {
+
+    // 1. Create the map from attributes to list of (target, configuration) pairs.
+    ListMultimap<Attribute, Dependency> depValueNames;
+    try {
+      depValueNames = resolver.dependentNodeMap(ctgValue, aspectDefinition, configConditions);
+    } catch (EvalException e) {
+      env.getListener().handle(Event.error(e.getLocation(), e.getMessage()));
+      throw new DependencyEvaluationException(new ConfiguredValueCreationException(e.print()));
+    }
+
+    // 2. Resolve configured target dependencies and handle errors.
+    Map<SkyKey, ConfiguredTarget> depValues =
+        resolveConfiguredTargetDependencies(env, depValueNames.values(), ctgValue.getTarget());
+    if (depValues == null) {
+      return null;
+    }
+
+    // 3. Resolve required aspects.
+    ListMultimap<SkyKey, Aspect> depAspects = resolveAspectDependencies(
+        env, depValues, depValueNames.values());
+    if (depAspects == null) {
+      return null;
+    }
+
+    // 3. Merge the dependent configured targets and aspects into a single map.
+    return mergeAspects(depValueNames, depValues, depAspects);
+  }
+
+  /**
+   * Merges the each direct dependency configured target with the aspects associated with it.
+   *
+   * <p>Note that the combination of a configured target and its associated aspects are not
+   * represented by a Skyframe node. This is because there can possibly be many different
+   * combinations of aspects for a particular configured target, so it would result in a
+   * combinatiorial explosion of Skyframe nodes.
+   */
+  private static ListMultimap<Attribute, ConfiguredTarget> mergeAspects(
+      ListMultimap<Attribute, Dependency> depValueNames,
+      Map<SkyKey, ConfiguredTarget> depConfiguredTargetMap,
+      ListMultimap<SkyKey, Aspect> depAspectMap) {
+    ListMultimap<Attribute, ConfiguredTarget> result = ArrayListMultimap.create();
+
+    for (Map.Entry<Attribute, Dependency> entry : depValueNames.entries()) {
+      Dependency dep = entry.getValue();
+      SkyKey depKey = TO_KEYS.apply(dep);
+      ConfiguredTarget depConfiguredTarget = depConfiguredTargetMap.get(depKey);
+      result.put(entry.getKey(),
+          RuleConfiguredTarget.mergeAspects(depConfiguredTarget, depAspectMap.get(depKey)));
+    }
+
+    return result;
+  }
+
+  /**
+   * Given a list of {@link Dependency} objects, returns a multimap from the {@link SkyKey} of the
+   * dependency to the {@link Aspect} instances that should be merged into it.
+   *
+   * <p>Returns null if the required aspects are not computed yet.
+   */
+  @Nullable
+  private static ListMultimap<SkyKey, Aspect> resolveAspectDependencies(Environment env,
+      Map<SkyKey, ConfiguredTarget> configuredTargetMap, Iterable<Dependency> deps)
+      throws DependencyEvaluationException {
+    ListMultimap<SkyKey, Aspect> result = ArrayListMultimap.create();
+    Set<SkyKey> aspectKeys = new HashSet<>();
+    for (Dependency dep : deps) {
+      for (Class<? extends ConfiguredAspectFactory> depAspect : dep.getAspects()) {
+        aspectKeys.add(AspectValue.key(dep.getLabel(), dep.getConfiguration(), depAspect));
+      }
+    }
+
+    Map<SkyKey, ValueOrException3<
+        AspectCreationException, NoSuchThingException, ConfiguredValueCreationException>>
+        depAspects = env.getValuesOrThrow(aspectKeys, AspectCreationException.class,
+            NoSuchThingException.class, ConfiguredValueCreationException.class);
+
+    for (Dependency dep : deps) {
+      SkyKey depKey = TO_KEYS.apply(dep);
+      ConfiguredTarget depConfiguredTarget = configuredTargetMap.get(depKey);
+      List<AspectValue> aspects = new ArrayList<>();
+      for (Class<? extends ConfiguredAspectFactory> depAspect : dep.getAspects()) {
+        if (!aspectMatchesConfiguredTarget(depConfiguredTarget, depAspect)) {
+          continue;
+        }
+
+        SkyKey aspectKey = AspectValue.key(dep.getLabel(), dep.getConfiguration(), depAspect);
+        AspectValue aspectValue = null;
+        try {
+          aspectValue = (AspectValue) depAspects.get(aspectKey).get();
+        } catch (ConfiguredValueCreationException e) {
+          // The configured target should have been created in resolveConfiguredTargetDependencies()
+          throw new IllegalStateException(e);
+        } catch (NoSuchThingException | AspectCreationException e) {
+          AspectFactory depAspectFactory = AspectFactory.Util.create(depAspect);
+          throw new DependencyEvaluationException(new ConfiguredValueCreationException(
+              String.format("Evaluation of aspect %s on %s failed: %s",
+                  depAspectFactory.getDefinition().getName(), dep.getLabel(), e.toString())));
+        }
+
+        if (aspectValue == null) {
+          // Dependent aspect has either not been computed yet or is in error.
+          return null;
+        }
+        result.put(depKey, aspectValue.get());
+      }
+    }
+
+    return result;
+  }
+
+  private static boolean aspectMatchesConfiguredTarget(ConfiguredTarget dep,
+      Class<? extends ConfiguredAspectFactory> aspectFactory) {
+    AspectDefinition aspectDefinition = AspectFactory.Util.create(aspectFactory).getDefinition();
+    for (Class<?> provider : aspectDefinition.getRequiredProviders()) {
+      if (dep.getProvider((Class<? extends TransitiveInfoProvider>) provider) == null) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Returns which aspects are computable based on the precise set of providers direct dependencies
+   * publish (and not the upper estimate in their rule definition).
+   *
+   * <p>An aspect is computable for a particular configured target if the configured target supplies
+   * all the providers the aspect requires.
+   *
+   * @param upperEstimate a multimap from attribute to the upper estimates computed by
+   *     {@link com.google.devtools.build.lib.analysis.DependencyResolver}.
+   * @param configuredTargetDeps a multimap from attribute to the directly dependent configured
+   *     targets
+   * @return a multimap from attribute to the more precise {@link Dependency} objects
+   */
+  private static ListMultimap<Attribute, Dependency> getComputableAspects(
+      ListMultimap<Attribute, Dependency> upperEstimate,
+      Map<SkyKey, ConfiguredTarget> configuredTargetDeps) {
+    ListMultimap<Attribute, Dependency> result = ArrayListMultimap.create();
+    for (Map.Entry<Attribute, Dependency> entry : upperEstimate.entries()) {
+      ConfiguredTarget dep =
+          configuredTargetDeps.get(TO_KEYS.apply(entry.getValue()));
+      List<Class<? extends ConfiguredAspectFactory>> depAspects = new ArrayList<>();
+      for (Class<? extends ConfiguredAspectFactory> candidate : entry.getValue().getAspects()) {
+        boolean ok = true;
+        for (Class<?> requiredProvider :
+            AspectFactory.Util.create(candidate).getDefinition().getRequiredProviders()) {
+          if (dep.getProvider((Class<? extends TransitiveInfoProvider>) requiredProvider) == null) {
+            ok = false;
+            break;
+          }
+        }
+
+        if (ok) {
+          depAspects.add(candidate);
+        }
+      }
+
+      result.put(entry.getKey(), new Dependency(
+          entry.getValue().getLabel(), entry.getValue().getConfiguration(),
+          ImmutableSet.copyOf(depAspects)));
+    }
+
+    return result;
+  }
+
+  /**
+   * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes
+   * used by this rule.
+   *
+   * <p>>If the configured targets supplying those providers aren't yet resolved by the
+   * dependency resolver, returns null.
+   */
+  @Nullable
+  static Set<ConfigMatchingProvider> getConfigConditions(Target target, Environment env,
+      SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue)
+      throws DependencyEvaluationException {
+    if (!(target instanceof Rule)) {
+      return ImmutableSet.of();
+    }
+
+    ImmutableSet.Builder<ConfigMatchingProvider> configConditions = ImmutableSet.builder();
+
+    // Collect the labels of the configured targets we need to resolve.
+    ListMultimap<Attribute, LabelAndConfiguration> configLabelMap = ArrayListMultimap.create();
+    RawAttributeMapper attributeMap = RawAttributeMapper.of(((Rule) target));
+    for (Attribute a : ((Rule) target).getAttributes()) {
+      for (Label configLabel : attributeMap.getConfigurabilityKeys(a.getName(), a.getType())) {
+        if (!Type.Selector.isReservedLabel(configLabel)) {
+          configLabelMap.put(a, LabelAndConfiguration.of(
+              configLabel, ctgValue.getConfiguration()));
+        }
+      }
+    }
+    if (configLabelMap.isEmpty()) {
+      return ImmutableSet.of();
+    }
+
+    // Collect the corresponding Skyframe configured target values. Abort early if they haven't
+    // been computed yet.
+    Collection<Dependency> configValueNames =
+        resolver.resolveRuleLabels(ctgValue, null, configLabelMap);
+    Map<SkyKey, ConfiguredTarget> configValues =
+        resolveConfiguredTargetDependencies(env, configValueNames, target);
+    if (configValues == null) {
+      return null;
+    }
+
+    // Get the configured targets as ConfigMatchingProvider interfaces.
+    for (Dependency entry : configValueNames) {
+      ConfiguredTarget value = configValues.get(TO_KEYS.apply(entry));
+      // The code above guarantees that value is non-null here.
+      ConfigMatchingProvider provider = value.getProvider(ConfigMatchingProvider.class);
+      if (provider != null) {
+        configConditions.add(provider);
+      } else {
+        // Not a valid provider for configuration conditions.
+        String message =
+            entry.getLabel() + " is not a valid configuration key for " + target.getLabel();
+        env.getListener().handle(Event.error(TargetUtils.getLocationMaybe(target), message));
+        throw new DependencyEvaluationException(new ConfiguredValueCreationException(message));
+      }
+    }
+
+    return configConditions.build();
+  }
+
+  /***
+   * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget
+   * instances.
+   *
+   * <p>Returns null if not all instances are available yet.
+   *
+   */
+  @Nullable
+  private static Map<SkyKey, ConfiguredTarget> resolveConfiguredTargetDependencies(
+      Environment env, Collection<Dependency> deps, Target target)
+      throws DependencyEvaluationException {
+    boolean ok = !env.valuesMissing();
+    String message = null;
+    Iterable<SkyKey> depKeys = Iterables.transform(deps, TO_KEYS);
+    // TODO(bazel-team): maybe having a two-exception argument is better than typing a generic
+    // Exception here.
+    Map<SkyKey, ValueOrException2<NoSuchTargetException,
+        NoSuchPackageException>> depValuesOrExceptions = env.getValuesOrThrow(depKeys,
+            NoSuchTargetException.class, NoSuchPackageException.class);
+    Map<SkyKey, ConfiguredTarget> depValues = new HashMap<>(depValuesOrExceptions.size());
+    SkyKey childKey = null;
+    NoSuchThingException transitiveChildException = null;
+    for (Map.Entry<SkyKey, ValueOrException2<NoSuchTargetException, NoSuchPackageException>> entry
+        : depValuesOrExceptions.entrySet()) {
+      ConfiguredTargetKey depKey = (ConfiguredTargetKey) entry.getKey().argument();
+      LabelAndConfiguration depLabelAndConfiguration = LabelAndConfiguration.of(
+          depKey.getLabel(), depKey.getConfiguration());
+      Label depLabel = depLabelAndConfiguration.getLabel();
+      ConfiguredTargetValue depValue = null;
+      NoSuchThingException directChildException = null;
+      try {
+        depValue = (ConfiguredTargetValue) entry.getValue().get();
+      } catch (NoSuchTargetException e) {
+        if (depLabel.equals(e.getLabel())) {
+          directChildException = e;
+        } else {
+          childKey = entry.getKey();
+          transitiveChildException = e;
+        }
+      } catch (NoSuchPackageException e) {
+        if (depLabel.getPackageName().equals(e.getPackageName())) {
+          directChildException = e;
+        } else {
+          childKey = entry.getKey();
+          transitiveChildException = e;
+        }
+      }
+      // If an exception wasn't caused by a direct child target value, we'll treat it the same
+      // as any other missing dep by setting ok = false below, and returning null at the end.
+      if (directChildException != null) {
+        // Only update messages for missing targets we depend on directly.
+        message = TargetUtils.formatMissingEdge(target, depLabel, directChildException);
+        env.getListener().handle(Event.error(TargetUtils.getLocationMaybe(target), message));
+      }
+
+      if (depValue == null) {
+        ok = false;
+      } else {
+        depValues.put(entry.getKey(), depValue.getConfiguredTarget());
+      }
+    }
+    if (message != null) {
+      throw new DependencyEvaluationException(new NoSuchTargetException(message));
+    }
+    if (childKey != null) {
+      throw new DependencyEvaluationException(childKey, transitiveChildException);
+    }
+    if (!ok) {
+      return null;
+    } else {
+      return depValues;
+    }
+  }
+
+
+  @Override
+  public String extractTag(SkyKey skyKey) {
+    return Label.print(((ConfiguredTargetKey) skyKey.argument()).getLabel());
+  }
+
+  @Nullable
+  private ConfiguredTargetValue createConfiguredTarget(SkyframeBuildView view,
+      Environment env, Target target, BuildConfiguration configuration,
+      ListMultimap<Attribute, ConfiguredTarget> depValueMap,
+      Set<ConfigMatchingProvider> configConditions)
+      throws ConfiguredTargetFunctionException,
+      InterruptedException {
+    boolean extendedSanityChecks = configuration != null && configuration.extendedSanityChecks();
+
+    StoredEventHandler events = new StoredEventHandler();
+    BuildConfiguration ownerConfig = (configuration == null)
+        ? null : configuration.getArtifactOwnerConfiguration();
+    boolean allowRegisteringActions = configuration == null || configuration.isActionsEnabled();
+    CachingAnalysisEnvironment analysisEnvironment = view.createAnalysisEnvironment(
+        new ConfiguredTargetKey(target.getLabel(), ownerConfig), false,
+        extendedSanityChecks, events, env, allowRegisteringActions);
+    if (env.valuesMissing()) {
+      return null;
+    }
+
+    ConfiguredTarget configuredTarget = view.createConfiguredTarget(target, configuration,
+        analysisEnvironment, depValueMap, configConditions);
+
+    events.replayOn(env.getListener());
+    if (events.hasErrors()) {
+      analysisEnvironment.disable(target);
+      throw new ConfiguredTargetFunctionException(new ConfiguredValueCreationException(
+              "Analysis of target '" + target.getLabel() + "' failed; build aborted"));
+    }
+    Preconditions.checkState(!analysisEnvironment.hasErrors(),
+        "Analysis environment hasError() but no errors reported");
+    if (env.valuesMissing()) {
+      return null;
+    }
+
+    analysisEnvironment.disable(target);
+    Preconditions.checkNotNull(configuredTarget, target);
+
+    return new ConfiguredTargetValue(configuredTarget,
+        ImmutableList.copyOf(analysisEnvironment.getRegisteredActions()));
+  }
+
+  /**
+   * An exception indicating that there was a problem during the construction of
+   * a ConfiguredTargetValue.
+   */
+  public static final class ConfiguredValueCreationException extends Exception {
+
+    public ConfiguredValueCreationException(String message) {
+      super(message);
+    }
+  }
+
+  /**
+   * Used to declare all the exception types that can be wrapped in the exception thrown by
+   * {@link ConfiguredTargetFunction#compute}.
+   */
+  public static final class ConfiguredTargetFunctionException extends SkyFunctionException {
+    public ConfiguredTargetFunctionException(NoSuchTargetException e) {
+      super(e, Transience.PERSISTENT);
+    }
+
+    private ConfiguredTargetFunctionException(ConfiguredValueCreationException error) {
+      super(error, Transience.PERSISTENT);
+    };
+
+    private ConfiguredTargetFunctionException(
+        @Nullable SkyKey childKey, Exception transitiveError) {
+      super(transitiveError, childKey);
+    }
+  }
+}