Fix users of toolchain resolution to call the new skyfunction.

Part of work on execution transitions, #7935.

Closes #8102.

PiperOrigin-RevId: 244878862
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainResolver.java
deleted file mode 100644
index 4a92d5b..0000000
--- a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainResolver.java
+++ /dev/null
@@ -1,507 +0,0 @@
-// Copyright 2018 The Bazel Authors. 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.analysis;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static java.util.stream.Collectors.joining;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Table;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
-import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
-import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
-import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
-import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
-import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil;
-import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
-import com.google.devtools.build.lib.skyframe.PlatformLookupUtil;
-import com.google.devtools.build.lib.skyframe.PlatformLookupUtil.InvalidPlatformException;
-import com.google.devtools.build.lib.skyframe.RegisteredExecutionPlatformsValue;
-import com.google.devtools.build.lib.skyframe.RegisteredToolchainsFunction.InvalidToolchainLabelException;
-import com.google.devtools.build.lib.skyframe.SingleToolchainResolutionFunction;
-import com.google.devtools.build.lib.skyframe.SingleToolchainResolutionFunction.NoToolchainFoundException;
-import com.google.devtools.build.lib.skyframe.SingleToolchainResolutionValue;
-import com.google.devtools.build.lib.skyframe.ToolchainException;
-import com.google.devtools.build.lib.skyframe.UnloadedToolchainContext;
-import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyKey;
-import com.google.devtools.build.skyframe.ValueOrException2;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.annotation.Nullable;
-
-/**
- * Performs the toolchain resolution process to determine the correct toolchain target dependencies
- * for a target being configured, based on the required toolchain types, target platform, and
- * available execution platforms.
- */
-public class ToolchainResolver {
-  // Required data.
-  private final Environment environment;
-  private final BuildConfigurationValue.Key configurationKey;
-
-  // Optional data.
-  private ImmutableSet<Label> requiredToolchainTypeLabels = ImmutableSet.of();
-  private ImmutableSet<Label> execConstraintLabels = ImmutableSet.of();
-  private boolean shouldSanityCheckConfiguration = false;
-
-  // Determined during execution.
-  private boolean debug = false;
-
-  /**
-   * Creates a new {@link ToolchainResolver} to help find the required toolchains for a configured
-   * target.
-   *
-   * @param env the environment to use to request dependent Skyframe nodes
-   * @param configurationKey The build configuration to use for dependent targets
-   */
-  public ToolchainResolver(Environment env, BuildConfigurationValue.Key configurationKey) {
-    this.environment = checkNotNull(env);
-    this.configurationKey = checkNotNull(configurationKey);
-  }
-
-  /**
-   * Sets the labels of the required toolchain types that this resolver needs to find toolchains
-   * for.
-   */
-  public ToolchainResolver setRequiredToolchainTypes(Set<Label> requiredToolchainTypeLabels) {
-    this.requiredToolchainTypeLabels = ImmutableSet.copyOf(requiredToolchainTypeLabels);
-    return this;
-  }
-
-  /**
-   * Sets extra constraints on the execution platform. Targets can use this to ensure that the
-   * execution platform has some desired characteristics, such as having enough memory to run tests.
-   */
-  public ToolchainResolver setExecConstraintLabels(Set<Label> execConstraintLabels) {
-    this.execConstraintLabels = ImmutableSet.copyOf(execConstraintLabels);
-    return this;
-  }
-
-  /**
-   * Sets whether the experimental retroactive trimming mode is in use. This determines whether
-   * sanity checks regarding the fragments in use for the configurations of platforms and toolchains
-   * are used - specifically, whether platforms use only the PlatformConfiguration, and toolchains
-   * do not use any configuration at all.
-   */
-  public ToolchainResolver setShouldSanityCheckConfiguration(boolean useSanityChecks) {
-    this.shouldSanityCheckConfiguration = useSanityChecks;
-    return this;
-  }
-
-  /**
-   * Determines the specific toolchains that are required, given the requested toolchain types,
-   * target platform, and configuration.
-   *
-   * <p>In order to resolve toolchains, first the {@link ToolchainResolver} must be created, and
-   * then an {@link UnloadedToolchainContext} generated. The {@link UnloadedToolchainContext} will
-   * report the specific toolchain targets to depend on, and those can be found using the typical
-   * dependency machinery. Once dependencies, including toolchains, have been loaded, the {@link
-   * ResolvedToolchainContext#load} method can be called to generate the final {@link
-   * ResolvedToolchainContext} to be used by the target.
-   *
-   * <p>This makes several SkyFrame calls, particularly to {@link
-   * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction} (to load platforms and
-   * toolchains), to {@link
-   * com.google.devtools.build.lib.skyframe.RegisteredExecutionPlatformsFunction}, and to {@link
-   * SingleToolchainResolutionFunction}. This method returns {@code null} to signal a SkyFrame
-   * restart is needed to resolve dependencies.
-   */
-  @Nullable
-  public UnloadedToolchainContext resolve() throws InterruptedException, ToolchainException {
-
-    try {
-      UnloadedToolchainContext.Builder unloadedToolchainContext =
-          UnloadedToolchainContext.builder();
-
-      // Determine the configuration being used.
-      BuildConfigurationValue value =
-          (BuildConfigurationValue) environment.getValue(configurationKey);
-      if (value == null) {
-        throw new ValueMissingException();
-      }
-      BuildConfiguration configuration = value.getConfiguration();
-      PlatformConfiguration platformConfiguration =
-          configuration.getFragment(PlatformConfiguration.class);
-      if (platformConfiguration == null) {
-        throw new ValueMissingException();
-      }
-
-      // Check if debug output should be generated.
-      this.debug = configuration.getOptions().get(PlatformOptions.class).toolchainResolutionDebug;
-
-      // Create keys for all platforms that will be used, and validate them early.
-      PlatformKeys platformKeys = loadPlatformKeys(configuration, platformConfiguration);
-      if (environment.valuesMissing()) {
-        return null;
-      }
-
-      // Determine the actual toolchain implementations to use.
-      determineToolchainImplementations(unloadedToolchainContext, platformKeys);
-
-      return unloadedToolchainContext.build();
-    } catch (ValueMissingException e) {
-      return null;
-    }
-  }
-
-  @AutoValue
-  abstract static class PlatformKeys {
-    abstract ConfiguredTargetKey hostPlatformKey();
-
-    abstract ConfiguredTargetKey targetPlatformKey();
-
-    abstract ImmutableList<ConfiguredTargetKey> executionPlatformKeys();
-
-    static PlatformKeys create(
-        ConfiguredTargetKey hostPlatformKey,
-        ConfiguredTargetKey targetPlatformKey,
-        List<ConfiguredTargetKey> executionPlatformKeys) {
-      return new AutoValue_ToolchainResolver_PlatformKeys(
-          hostPlatformKey, targetPlatformKey, ImmutableList.copyOf(executionPlatformKeys));
-    }
-  }
-
-  private PlatformKeys loadPlatformKeys(
-      BuildConfiguration configuration, PlatformConfiguration platformConfiguration)
-      throws InterruptedException, InvalidPlatformException, ValueMissingException,
-          InvalidConstraintValueException {
-    // Determine the target and host platform keys.
-    Label hostPlatformLabel = platformConfiguration.getHostPlatform();
-    Label targetPlatformLabel = platformConfiguration.getTargetPlatform();
-
-    ConfiguredTargetKey hostPlatformKey = ConfiguredTargetKey.of(hostPlatformLabel, configuration);
-    ConfiguredTargetKey targetPlatformKey =
-        ConfiguredTargetKey.of(targetPlatformLabel, configuration);
-
-    // Load the host and target platforms early, to check for errors.
-    PlatformLookupUtil.getPlatformInfo(
-        ImmutableList.of(hostPlatformKey, targetPlatformKey),
-        environment,
-        shouldSanityCheckConfiguration);
-    if (environment.valuesMissing()) {
-      throw new ValueMissingException();
-    }
-
-    ImmutableList<ConfiguredTargetKey> executionPlatformKeys =
-        loadExecutionPlatformKeys(configuration, hostPlatformKey);
-
-    return PlatformKeys.create(hostPlatformKey, targetPlatformKey, executionPlatformKeys);
-  }
-
-  private ImmutableList<ConfiguredTargetKey> loadExecutionPlatformKeys(
-      BuildConfiguration configuration, ConfiguredTargetKey defaultPlatformKey)
-      throws InvalidPlatformException, InterruptedException, InvalidConstraintValueException,
-          ValueMissingException {
-    RegisteredExecutionPlatformsValue registeredExecutionPlatforms =
-        (RegisteredExecutionPlatformsValue)
-            environment.getValueOrThrow(
-                RegisteredExecutionPlatformsValue.key(configurationKey),
-                InvalidPlatformException.class);
-    if (registeredExecutionPlatforms == null) {
-      throw new ValueMissingException();
-    }
-
-    ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys =
-        new ImmutableList.Builder<ConfiguredTargetKey>()
-            .addAll(registeredExecutionPlatforms.registeredExecutionPlatformKeys())
-            .add(defaultPlatformKey)
-            .build();
-
-    // Filter out execution platforms that don't satisfy the extra constraints.
-    ImmutableList<ConfiguredTargetKey> execConstraintKeys =
-        execConstraintLabels.stream()
-            .map(label -> ConfiguredTargetKey.of(label, configuration))
-            .collect(toImmutableList());
-
-    return filterAvailablePlatforms(availableExecutionPlatformKeys, execConstraintKeys);
-  }
-
-  /** Returns only the platform keys that match the given constraints. */
-  private ImmutableList<ConfiguredTargetKey> filterAvailablePlatforms(
-      ImmutableList<ConfiguredTargetKey> platformKeys,
-      ImmutableList<ConfiguredTargetKey> constraintKeys)
-      throws InterruptedException, InvalidPlatformException, InvalidConstraintValueException,
-          ValueMissingException {
-
-    // Short circuit if not needed.
-    if (constraintKeys.isEmpty()) {
-      return platformKeys;
-    }
-
-    // At this point the host and target platforms have been loaded, but not necessarily the chosen
-    // execution platform (it might be the same as the host platform, and might not).
-    //
-    // It's not worth trying to optimize away this call, since in the optimizable case (the exec
-    // platform is the host platform), Skyframe will return the correct results immediately without
-    // need of a restart.
-    Map<ConfiguredTargetKey, PlatformInfo> platformInfoMap =
-        PlatformLookupUtil.getPlatformInfo(
-            platformKeys, environment, shouldSanityCheckConfiguration);
-    if (platformInfoMap == null) {
-      throw new ValueMissingException();
-    }
-    List<ConstraintValueInfo> constraints =
-        ConstraintValueLookupUtil.getConstraintValueInfo(constraintKeys, environment);
-    if (constraints == null) {
-      throw new ValueMissingException();
-    }
-
-    return platformKeys.stream()
-        .filter(key -> filterPlatform(platformInfoMap.get(key), constraints))
-        .collect(toImmutableList());
-  }
-
-  /** Returns {@code true} if the given platform has all of the constraints. */
-  private boolean filterPlatform(PlatformInfo platformInfo, List<ConstraintValueInfo> constraints) {
-    ImmutableList<ConstraintValueInfo> missingConstraints =
-        platformInfo.constraints().findMissing(constraints);
-    if (debug) {
-      for (ConstraintValueInfo constraint : missingConstraints) {
-        // The value for this setting is not present in the platform, or doesn't match the expected
-        // value.
-        environment
-            .getListener()
-            .handle(
-                Event.info(
-                    String.format(
-                        "ToolchainResolver: Removed execution platform %s from"
-                            + " available execution platforms, it is missing constraint %s",
-                        platformInfo.label(), constraint.label())));
-        }
-    }
-
-    return missingConstraints.isEmpty();
-  }
-
-  private void determineToolchainImplementations(
-      UnloadedToolchainContext.Builder unloadedToolchainContext, PlatformKeys platformKeys)
-      throws InterruptedException, ToolchainException, ValueMissingException {
-
-    // Find the toolchains for the required toolchain types.
-    List<SingleToolchainResolutionValue.Key> registeredToolchainKeys = new ArrayList<>();
-    for (Label toolchainTypeLabel : requiredToolchainTypeLabels) {
-      registeredToolchainKeys.add(
-          SingleToolchainResolutionValue.key(
-              configurationKey,
-              toolchainTypeLabel,
-              platformKeys.targetPlatformKey(),
-              platformKeys.executionPlatformKeys()));
-    }
-
-    Map<SkyKey, ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>>
-        results =
-            environment.getValuesOrThrow(
-                registeredToolchainKeys,
-                NoToolchainFoundException.class,
-                InvalidToolchainLabelException.class);
-    boolean valuesMissing = false;
-
-    // Determine the potential set of toolchains.
-    Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains =
-        HashBasedTable.create();
-    ImmutableSet.Builder<ToolchainTypeInfo> requiredToolchainTypesBuilder = ImmutableSet.builder();
-    List<Label> missingToolchains = new ArrayList<>();
-    for (Map.Entry<
-            SkyKey, ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>>
-        entry : results.entrySet()) {
-      try {
-        ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>
-            valueOrException = entry.getValue();
-        SingleToolchainResolutionValue singleToolchainResolutionValue =
-            (SingleToolchainResolutionValue) valueOrException.get();
-        if (singleToolchainResolutionValue == null) {
-          valuesMissing = true;
-          continue;
-        }
-
-        ToolchainTypeInfo requiredToolchainType = singleToolchainResolutionValue.toolchainType();
-        requiredToolchainTypesBuilder.add(requiredToolchainType);
-        resolvedToolchains.putAll(
-            findPlatformsAndLabels(requiredToolchainType, singleToolchainResolutionValue));
-      } catch (NoToolchainFoundException e) {
-        // Save the missing type and continue looping to check for more.
-        missingToolchains.add(e.missingToolchainTypeLabel());
-      }
-    }
-
-    if (!missingToolchains.isEmpty()) {
-      throw new UnresolvedToolchainsException(missingToolchains);
-    }
-
-    if (valuesMissing) {
-      throw new ValueMissingException();
-    }
-
-    ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes = requiredToolchainTypesBuilder.build();
-
-    // Find and return the first execution platform which has all required toolchains.
-    Optional<ConfiguredTargetKey> selectedExecutionPlatformKey;
-    if (requiredToolchainTypeLabels.isEmpty()
-        && platformKeys.executionPlatformKeys().contains(platformKeys.hostPlatformKey())) {
-      // Fall back to the legacy behavior: use the host platform if it's available, otherwise the
-      // first execution platform.
-      selectedExecutionPlatformKey = Optional.of(platformKeys.hostPlatformKey());
-    } else {
-      // If there are no toolchains, this will return the first execution platform.
-      selectedExecutionPlatformKey =
-          findExecutionPlatformForToolchains(
-              requiredToolchainTypes, platformKeys.executionPlatformKeys(), resolvedToolchains);
-    }
-
-    if (!selectedExecutionPlatformKey.isPresent()) {
-      throw new NoMatchingPlatformException(
-          requiredToolchainTypeLabels,
-          platformKeys.executionPlatformKeys(),
-          platformKeys.targetPlatformKey());
-    }
-
-    Map<ConfiguredTargetKey, PlatformInfo> platforms =
-        PlatformLookupUtil.getPlatformInfo(
-            ImmutableList.of(selectedExecutionPlatformKey.get(), platformKeys.targetPlatformKey()),
-            environment,
-            shouldSanityCheckConfiguration);
-    if (platforms == null) {
-      throw new ValueMissingException();
-    }
-
-    unloadedToolchainContext.setRequiredToolchainTypes(requiredToolchainTypes);
-    unloadedToolchainContext.setExecutionPlatform(
-        platforms.get(selectedExecutionPlatformKey.get()));
-    unloadedToolchainContext.setTargetPlatform(platforms.get(platformKeys.targetPlatformKey()));
-
-    Map<ToolchainTypeInfo, Label> toolchains =
-        resolvedToolchains.row(selectedExecutionPlatformKey.get());
-    unloadedToolchainContext.setToolchainTypeToResolved(ImmutableBiMap.copyOf(toolchains));
-  }
-
-  /**
-   * Adds all of toolchain labels from{@code toolchainResolutionValue} to {@code
-   * resolvedToolchains}.
-   */
-  private static Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> findPlatformsAndLabels(
-      ToolchainTypeInfo requiredToolchainType,
-      SingleToolchainResolutionValue singleToolchainResolutionValue) {
-
-    Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains =
-        HashBasedTable.create();
-    for (Map.Entry<ConfiguredTargetKey, Label> entry :
-        singleToolchainResolutionValue.availableToolchainLabels().entrySet()) {
-      resolvedToolchains.put(entry.getKey(), requiredToolchainType, entry.getValue());
-    }
-    return resolvedToolchains;
-  }
-
-  /**
-   * Finds the first platform from {@code availableExecutionPlatformKeys} that is present in {@code
-   * resolvedToolchains} and has all required toolchain types.
-   */
-  private Optional<ConfiguredTargetKey> findExecutionPlatformForToolchains(
-      ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes,
-      ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
-      Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains) {
-    for (ConfiguredTargetKey executionPlatformKey : availableExecutionPlatformKeys) {
-      Map<ToolchainTypeInfo, Label> toolchains = resolvedToolchains.row(executionPlatformKey);
-
-      if (!toolchains.keySet().containsAll(requiredToolchainTypes)) {
-        // Not all toolchains are present, keep going
-        continue;
-      }
-
-      if (debug) {
-        String selectedToolchains =
-            toolchains.entrySet().stream()
-                .map(
-                    e ->
-                        String.format(
-                            "type %s -> toolchain %s", e.getKey().typeLabel(), e.getValue()))
-                .collect(joining(", "));
-        environment
-            .getListener()
-            .handle(
-                Event.info(
-                    String.format(
-                        "ToolchainResolver: Selected execution platform %s, %s",
-                        executionPlatformKey.getLabel(), selectedToolchains)));
-      }
-      return Optional.of(executionPlatformKey);
-    }
-
-    return Optional.empty();
-  }
-
-  private static final class ValueMissingException extends Exception {
-    private ValueMissingException() {
-      super();
-    }
-  }
-
-  /** Exception used when no execution platform can be found. */
-  static final class NoMatchingPlatformException extends ToolchainException {
-    NoMatchingPlatformException(
-        Set<Label> requiredToolchainTypeLabels,
-        ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
-        ConfiguredTargetKey targetPlatformKey) {
-      super(
-          formatError(
-              requiredToolchainTypeLabels, availableExecutionPlatformKeys, targetPlatformKey));
-    }
-
-    private static String formatError(
-        Set<Label> requiredToolchainTypeLabels,
-        ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
-        ConfiguredTargetKey targetPlatformKey) {
-      if (requiredToolchainTypeLabels.isEmpty()) {
-        return String.format(
-            "Unable to find an execution platform for target platform %s"
-                + " from available execution platforms [%s]",
-            targetPlatformKey.getLabel(),
-            availableExecutionPlatformKeys.stream()
-                .map(key -> key.getLabel().toString())
-                .collect(Collectors.joining(", ")));
-      }
-      return String.format(
-          "Unable to find an execution platform for toolchains [%s] and target platform %s"
-              + " from available execution platforms [%s]",
-          requiredToolchainTypeLabels.stream().map(Label::toString).collect(joining(", ")),
-          targetPlatformKey.getLabel(),
-          availableExecutionPlatformKeys.stream()
-              .map(key -> key.getLabel().toString())
-              .collect(Collectors.joining(", ")));
-    }
-  }
-
-  /** Exception used when a toolchain type is required but no matching toolchain is found. */
-  static final class UnresolvedToolchainsException extends ToolchainException {
-    UnresolvedToolchainsException(List<Label> missingToolchainTypes) {
-      super(
-          String.format(
-              "no matching toolchains found for types %s",
-              missingToolchainTypes.stream().map(Label::toString).collect(joining(", "))));
-    }
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
index dff58a5..edefd40 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.lib.query2;
 
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -368,17 +369,26 @@
 
   protected abstract RuleConfiguredTarget getRuleConfiguredTarget(T target);
 
+  protected Collection<T> targetifyValues(Iterable<SkyKey> dependencies)
+      throws InterruptedException {
+    Collection<T> values = new ArrayList<>();
+    for (SkyKey key : dependencies) {
+      if (key.functionName().equals(SkyFunctions.CONFIGURED_TARGET)) {
+        values.add(getValueFromKey(key));
+      } else if (key.functionName().equals(SkyFunctions.TOOLCHAIN_RESOLUTION)) {
+        // Also fetch these dependencies.
+        Collection<T> toolchainDeps = targetifyValues(graph.getDirectDeps(key));
+        values.addAll(toolchainDeps);
+      }
+    }
+    return values;
+  }
+
   protected Map<SkyKey, Collection<T>> targetifyValues(
       Map<SkyKey, ? extends Iterable<SkyKey>> input) throws InterruptedException {
     Map<SkyKey, Collection<T>> result = new HashMap<>();
     for (Map.Entry<SkyKey, ? extends Iterable<SkyKey>> entry : input.entrySet()) {
-      Collection<T> value = new ArrayList<>();
-      for (SkyKey key : entry.getValue()) {
-        if (key.functionName().equals(SkyFunctions.CONFIGURED_TARGET)) {
-          value.add(getValueFromKey(key));
-        }
-      }
-      result.put(entry.getKey(), value);
+      result.put(entry.getKey(), targetifyValues(entry.getValue()));
     }
     return result;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index 743c7d2..d278350 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -31,7 +31,6 @@
 import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
 import com.google.devtools.build.lib.analysis.ResolvedToolchainContext;
 import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
-import com.google.devtools.build.lib.analysis.ToolchainResolver;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
@@ -413,9 +412,15 @@
         try {
           ImmutableSet<Label> requiredToolchains = aspect.getDefinition().getRequiredToolchains();
           unloadedToolchainContext =
-              new ToolchainResolver(env, BuildConfigurationValue.key(configuration))
-                  .setRequiredToolchainTypes(requiredToolchains)
-                  .resolve();
+              (UnloadedToolchainContext)
+                  env.getValueOrThrow(
+                      UnloadedToolchainContext.key()
+                          .configurationKey(BuildConfigurationValue.key(configuration))
+                          .requiredToolchainTypeLabels(requiredToolchains)
+                          .shouldSanityCheckConfiguration(
+                              configuration.trimConfigurationsRetroactively())
+                          .build(),
+                      ToolchainException.class);
         } catch (ToolchainException e) {
           // TODO(katre): better error handling
           throw new AspectCreationException(
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
index a266129..1e36cb7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -37,7 +37,6 @@
 import com.google.devtools.build.lib.analysis.EmptyConfiguredTarget;
 import com.google.devtools.build.lib.analysis.ResolvedToolchainContext;
 import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
-import com.google.devtools.build.lib.analysis.ToolchainResolver;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
@@ -309,12 +308,16 @@
           // Collect local (target, rule) constraints for filtering out execution platforms.
           ImmutableSet<Label> execConstraintLabels = getExecutionPlatformConstraints(rule);
           unloadedToolchainContext =
-              new ToolchainResolver(env, configuredTargetKey.getConfigurationKey())
-                  .setRequiredToolchainTypes(requiredToolchains)
-                  .setExecConstraintLabels(execConstraintLabels)
-                  .setShouldSanityCheckConfiguration(
-                      configuration.trimConfigurationsRetroactively())
-                  .resolve();
+              (UnloadedToolchainContext)
+                  env.getValueOrThrow(
+                      UnloadedToolchainContext.key()
+                          .configurationKey(configuredTargetKey.getConfigurationKey())
+                          .requiredToolchainTypeLabels(requiredToolchains)
+                          .execConstraintLabels(execConstraintLabels)
+                          .shouldSanityCheckConfiguration(
+                              configuration.trimConfigurationsRetroactively())
+                          .build(),
+                      ToolchainException.class);
           if (env.valuesMissing()) {
             return null;
           }
@@ -426,10 +429,8 @@
               e.getCauses()));
     } catch (ToolchainException e) {
       // We need to throw a ConfiguredValueCreationException, so either find one or make one.
-      ConfiguredValueCreationException cvce;
-      if (e.getCause() instanceof ConfiguredValueCreationException) {
-        cvce = (ConfiguredValueCreationException) e.getCause();
-      } else {
+      ConfiguredValueCreationException cvce = e.asConfiguredValueCreationException();
+      if (cvce == null) {
         cvce =
             new ConfiguredValueCreationException(e.getMessage(), target.getLabel(), configuration);
       }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
index da00c9f..76cdaf3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
@@ -138,7 +138,7 @@
       SkyFunctionName.createHermetic("REGISTERED_TOOLCHAINS");
   static final SkyFunctionName SINGLE_TOOLCHAIN_RESOLUTION =
       SkyFunctionName.createHermetic("SINGLE_TOOLCHAIN_RESOLUTION");
-  static final SkyFunctionName TOOLCHAIN_RESOLUTION =
+  public static final SkyFunctionName TOOLCHAIN_RESOLUTION =
       SkyFunctionName.createHermetic("TOOLCHAIN_RESOLUTION");
   public static final SkyFunctionName REPOSITORY_MAPPING =
       SkyFunctionName.createHermetic("REPOSITORY_MAPPING");
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
index d39d838..d2bf860 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
@@ -93,7 +93,6 @@
       // Determine the actual toolchain implementations to use.
       determineToolchainImplementations(
           env,
-          debug,
           key.configurationKey(),
           key.requiredToolchainTypeLabels(),
           builder,
@@ -275,7 +274,7 @@
             .handle(
                 Event.info(
                     String.format(
-                        "ToolchainResolver: Removed execution platform %s from"
+                        "ToolchainResolution: Removed execution platform %s from"
                             + " available execution platforms, it is missing constraint %s",
                         platformInfo.label(), constraint.label())));
       }
@@ -285,8 +284,7 @@
   }
 
   private void determineToolchainImplementations(
-      SkyFunction.Environment environment,
-      boolean debug,
+      Environment environment,
       BuildConfigurationValue.Key configurationKey,
       ImmutableSet<Label> requiredToolchainTypeLabels,
       UnloadedToolchainContext.Builder builder,
@@ -358,8 +356,6 @@
     if (!requiredToolchainTypeLabels.isEmpty()) {
       selectedExecutionPlatformKey =
           findExecutionPlatformForToolchains(
-              environment,
-              debug,
               requiredToolchainTypes,
               platformKeys.executionPlatformKeys(),
               resolvedToolchains);
@@ -400,7 +396,7 @@
   }
 
   /**
-   * Adds all of toolchain labels from{@code toolchainResolutionValue} to {@code
+   * Adds all of toolchain labels from {@code toolchainResolutionValue} to {@code
    * resolvedToolchains}.
    */
   private static Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> findPlatformsAndLabels(
@@ -421,8 +417,6 @@
    * resolvedToolchains} and has all required toolchain types.
    */
   private static Optional<ConfiguredTargetKey> findExecutionPlatformForToolchains(
-      SkyFunction.Environment environment,
-      boolean debug,
       ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes,
       ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
       Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains) {
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/ToolchainResolverTest.java b/src/test/java/com/google/devtools/build/lib/analysis/ToolchainResolverTest.java
deleted file mode 100644
index f50a399..0000000
--- a/src/test/java/com/google/devtools/build/lib/analysis/ToolchainResolverTest.java
+++ /dev/null
@@ -1,521 +0,0 @@
-// Copyright 2018 The Bazel Authors. 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.analysis;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.analysis.ToolchainResolver.NoMatchingPlatformException;
-import com.google.devtools.build.lib.analysis.ToolchainResolver.UnresolvedToolchainsException;
-import com.google.devtools.build.lib.analysis.util.AnalysisMock;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.rules.platform.ToolchainTestCase;
-import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
-import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
-import com.google.devtools.build.lib.skyframe.PlatformLookupUtil.InvalidPlatformException;
-import com.google.devtools.build.lib.skyframe.ToolchainException;
-import com.google.devtools.build.lib.skyframe.UnloadedToolchainContext;
-import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
-import com.google.devtools.build.skyframe.EvaluationResult;
-import com.google.devtools.build.skyframe.SkyFunction;
-import com.google.devtools.build.skyframe.SkyFunctionException;
-import com.google.devtools.build.skyframe.SkyFunctionName;
-import com.google.devtools.build.skyframe.SkyKey;
-import com.google.devtools.build.skyframe.SkyValue;
-import java.util.Set;
-import javax.annotation.Nullable;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for {@link ToolchainResolver}. */
-@RunWith(JUnit4.class)
-public class ToolchainResolverTest extends ToolchainTestCase {
-  /**
-   * An {@link AnalysisMock} that injects {@link ResolveToolchainsFunction} into the Skyframe
-   * executor.
-   */
-  private static final class LocalAnalysisMock extends AnalysisMock.Delegate {
-    LocalAnalysisMock() {
-      super(AnalysisMock.get());
-    }
-
-    @Override
-    public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctions(
-        BlazeDirectories directories) {
-      return ImmutableMap.<SkyFunctionName, SkyFunction>builder()
-          .putAll(super.getSkyFunctions(directories))
-          .put(RESOLVE_TOOLCHAINS_FUNCTION, new ResolveToolchainsFunction())
-          .build();
-    }
-  }
-
-  @Override
-  protected AnalysisMock getAnalysisMock() {
-    return new LocalAnalysisMock();
-  }
-
-  @Test
-  public void resolve() throws Exception {
-    // This should select platform mac, toolchain extra_toolchain_mac, because platform
-    // mac is listed first.
-    addToolchain(
-        "extra",
-        "extra_toolchain_linux",
-        ImmutableList.of("//constraints:linux"),
-        ImmutableList.of("//constraints:linux"),
-        "baz");
-    addToolchain(
-        "extra",
-        "extra_toolchain_mac",
-        ImmutableList.of("//constraints:mac"),
-        ImmutableList.of("//constraints:linux"),
-        "baz");
-    rewriteWorkspace(
-        "register_toolchains('//extra:extra_toolchain_linux', '//extra:extra_toolchain_mac')",
-        "register_execution_platforms('//platforms:mac', '//platforms:linux')");
-
-    useConfiguration("--platforms=//platforms:linux");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(ImmutableSet.of(testToolchainTypeLabel), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasNoError();
-    UnloadedToolchainContext unloadedToolchainContext = result.get(key).unloadedToolchainContext();
-    assertThat(unloadedToolchainContext).isNotNull();
-
-    assertThat(unloadedToolchainContext.requiredToolchainTypes())
-        .containsExactly(testToolchainType);
-    assertThat(unloadedToolchainContext.resolvedToolchainLabels())
-        .containsExactly(Label.parseAbsoluteUnchecked("//extra:extra_toolchain_mac_impl"));
-
-    assertThat(unloadedToolchainContext.executionPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.executionPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:mac"));
-
-    assertThat(unloadedToolchainContext.targetPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.targetPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:linux"));
-  }
-
-  @Test
-  public void resolve_noToolchainType() throws Exception {
-    scratch.file("host/BUILD", "platform(name = 'host')");
-    rewriteWorkspace("register_execution_platforms('//platforms:mac', '//platforms:linux')");
-
-    useConfiguration("--host_platform=//host:host", "--platforms=//platforms:linux");
-    ResolveToolchainsKey key = ResolveToolchainsKey.create(ImmutableSet.of(), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasNoError();
-    UnloadedToolchainContext unloadedToolchainContext = result.get(key).unloadedToolchainContext();
-    assertThat(unloadedToolchainContext).isNotNull();
-
-    assertThat(unloadedToolchainContext.requiredToolchainTypes()).isEmpty();
-
-    // With no toolchains requested, should fall back to the host platform.
-    assertThat(unloadedToolchainContext.executionPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.executionPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//host:host"));
-
-    assertThat(unloadedToolchainContext.targetPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.targetPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:linux"));
-  }
-
-  @Test
-  public void resolve_noToolchainType_hostNotAvailable() throws Exception {
-    scratch.file("host/BUILD", "platform(name = 'host')");
-    scratch.file(
-        "sample/BUILD",
-        "constraint_setting(name='demo')",
-        "constraint_value(name = 'demo_a', constraint_setting=':demo')",
-        "constraint_value(name = 'demo_b', constraint_setting=':demo')",
-        "platform(name = 'sample_a',",
-        "  constraint_values = [':demo_a'],",
-        ")",
-        "platform(name = 'sample_b',",
-        "  constraint_values = [':demo_b'],",
-        ")");
-    rewriteWorkspace(
-        "register_execution_platforms('//platforms:mac', '//platforms:linux',",
-        "    '//sample:sample_a', '//sample:sample_b')");
-
-    useConfiguration("--host_platform=//host:host", "--platforms=//platforms:linux");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(),
-            ImmutableSet.of(Label.parseAbsoluteUnchecked("//sample:demo_b")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasNoError();
-    UnloadedToolchainContext unloadedToolchainContext = result.get(key).unloadedToolchainContext();
-    assertThat(unloadedToolchainContext).isNotNull();
-
-    assertThat(unloadedToolchainContext.requiredToolchainTypes()).isEmpty();
-
-    assertThat(unloadedToolchainContext.executionPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.executionPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//sample:sample_b"));
-
-    assertThat(unloadedToolchainContext.targetPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.targetPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:linux"));
-  }
-
-  @Test
-  public void resolve_unavailableToolchainType_single() throws Exception {
-    useConfiguration("--host_platform=//platforms:linux", "--platforms=//platforms:mac");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(
-                testToolchainTypeLabel, Label.parseAbsoluteUnchecked("//fake/toolchain:type_1")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(UnresolvedToolchainsException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains("no matching toolchains found for types //fake/toolchain:type_1");
-  }
-
-  @Test
-  public void resolve_unavailableToolchainType_multiple() throws Exception {
-    useConfiguration("--host_platform=//platforms:linux", "--platforms=//platforms:mac");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(
-                testToolchainTypeLabel,
-                Label.parseAbsoluteUnchecked("//fake/toolchain:type_1"),
-                Label.parseAbsoluteUnchecked("//fake/toolchain:type_2")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(UnresolvedToolchainsException.class);
-    // Only one of the missing types will be reported, so do not check the specific error message.
-  }
-
-  @Test
-  public void resolve_invalidTargetPlatform_badTarget() throws Exception {
-    scratch.file("invalid/BUILD", "filegroup(name = 'not_a_platform')");
-    useConfiguration("--platforms=//invalid:not_a_platform");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(ImmutableSet.of(testToolchainTypeLabel), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(InvalidPlatformException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains(
-            "//invalid:not_a_platform was referenced as a platform, "
-                + "but does not provide PlatformInfo");
-  }
-
-  @Test
-  public void resolve_invalidTargetPlatform_badPackage() throws Exception {
-    scratch.resolve("invalid").delete();
-    useConfiguration("--platforms=//invalid:not_a_platform");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(ImmutableSet.of(testToolchainTypeLabel), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(InvalidPlatformException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains("BUILD file not found");
-  }
-
-  @Test
-  public void resolve_invalidHostPlatform() throws Exception {
-    scratch.file("invalid/BUILD", "filegroup(name = 'not_a_platform')");
-    useConfiguration("--host_platform=//invalid:not_a_platform");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(ImmutableSet.of(testToolchainTypeLabel), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(InvalidPlatformException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains("//invalid:not_a_platform");
-  }
-
-  @Test
-  public void resolve_invalidExecutionPlatform() throws Exception {
-    scratch.file("invalid/BUILD", "filegroup(name = 'not_a_platform')");
-    useConfiguration("--extra_execution_platforms=//invalid:not_a_platform");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(ImmutableSet.of(testToolchainTypeLabel), targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(InvalidPlatformException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains("//invalid:not_a_platform");
-  }
-
-  @Test
-  public void resolve_execConstraints() throws Exception {
-    // This should select platform linux, toolchain extra_toolchain_linux, due to extra constraints,
-    // even though platform mac is registered first.
-    addToolchain(
-        /* packageName= */ "extra",
-        /* toolchainName= */ "extra_toolchain_linux",
-        /* execConstraints= */ ImmutableList.of("//constraints:linux"),
-        /* targetConstraints= */ ImmutableList.of("//constraints:linux"),
-        /* data= */ "baz");
-    addToolchain(
-        /* packageName= */ "extra",
-        /* toolchainName= */ "extra_toolchain_mac",
-        /* execConstraints= */ ImmutableList.of("//constraints:mac"),
-        /* targetConstraints= */ ImmutableList.of("//constraints:linux"),
-        /* data= */ "baz");
-    rewriteWorkspace(
-        "register_toolchains('//extra:extra_toolchain_linux', '//extra:extra_toolchain_mac')",
-        "register_execution_platforms('//platforms:mac', '//platforms:linux')");
-
-    useConfiguration("--platforms=//platforms:linux");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(testToolchainTypeLabel),
-            ImmutableSet.of(Label.parseAbsoluteUnchecked("//constraints:linux")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasNoError();
-    UnloadedToolchainContext unloadedToolchainContext = result.get(key).unloadedToolchainContext();
-    assertThat(unloadedToolchainContext).isNotNull();
-
-    assertThat(unloadedToolchainContext.requiredToolchainTypes())
-        .containsExactly(testToolchainType);
-    assertThat(unloadedToolchainContext.resolvedToolchainLabels())
-        .containsExactly(Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl"));
-
-    assertThat(unloadedToolchainContext.executionPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.executionPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:linux"));
-
-    assertThat(unloadedToolchainContext.targetPlatform()).isNotNull();
-    assertThat(unloadedToolchainContext.targetPlatform().label())
-        .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:linux"));
-  }
-
-  @Test
-  public void resolve_execConstraints_invalid() throws Exception {
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(testToolchainTypeLabel),
-            ImmutableSet.of(Label.parseAbsoluteUnchecked("//platforms:linux")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(InvalidConstraintValueException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessageThat()
-        .contains("//platforms:linux");
-  }
-
-  @Test
-  public void resolve_noMatchingPlatform() throws Exception {
-    // Write toolchain A, and a toolchain implementing it.
-    scratch.appendFile(
-        "a/BUILD",
-        "toolchain_type(name = 'toolchain_type_A')",
-        "toolchain(",
-        "    name = 'toolchain',",
-        "    toolchain_type = ':toolchain_type_A',",
-        "    exec_compatible_with = ['//constraints:mac'],",
-        "    target_compatible_with = [],",
-        "    toolchain = ':toolchain_impl')",
-        "filegroup(name='toolchain_impl')");
-    // Write toolchain B, and a toolchain implementing it.
-    scratch.appendFile(
-        "b/BUILD",
-        "load('//toolchain:toolchain_def.bzl', 'test_toolchain')",
-        "toolchain_type(name = 'toolchain_type_B')",
-        "toolchain(",
-        "    name = 'toolchain',",
-        "    toolchain_type = ':toolchain_type_B',",
-        "    exec_compatible_with = ['//constraints:linux'],",
-        "    target_compatible_with = [],",
-        "    toolchain = ':toolchain_impl')",
-        "filegroup(name='toolchain_impl')");
-
-    rewriteWorkspace(
-        "register_toolchains('//a:toolchain', '//b:toolchain')",
-        "register_execution_platforms('//platforms:mac', '//platforms:linux')");
-
-    useConfiguration("--platforms=//platforms:linux");
-    ResolveToolchainsKey key =
-        ResolveToolchainsKey.create(
-            ImmutableSet.of(
-                Label.parseAbsoluteUnchecked("//a:toolchain_type_A"),
-                Label.parseAbsoluteUnchecked("//b:toolchain_type_B")),
-            targetConfigKey);
-
-    EvaluationResult<ResolveToolchainsValue> result = createToolchainContextBuilder(key);
-    assertThatEvaluationResult(result).hasError();
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(NoMatchingPlatformException.class);
-  }
-
-  private static final SkyFunctionName RESOLVE_TOOLCHAINS_FUNCTION =
-      SkyFunctionName.createHermetic("RESOLVE_TOOLCHAINS_FUNCTION");
-
-  @AutoValue
-  abstract static class ResolveToolchainsKey implements SkyKey {
-    @Override
-    public SkyFunctionName functionName() {
-      return RESOLVE_TOOLCHAINS_FUNCTION;
-    }
-
-    abstract ImmutableSet<Label> requiredToolchainTypes();
-
-    abstract ImmutableSet<Label> execConstraintLabels();
-
-    abstract BuildConfigurationValue.Key configurationKey();
-
-    public static ResolveToolchainsKey create(
-        Set<Label> requiredToolchains,
-        BuildConfigurationValue.Key configurationKey) {
-      return create(
-          requiredToolchains,
-          /* execConstraintLabels= */ ImmutableSet.of(),
-          configurationKey);
-    }
-
-    public static ResolveToolchainsKey create(
-        Set<Label> requiredToolchains,
-        Set<Label> execConstraintLabels,
-        BuildConfigurationValue.Key configurationKey) {
-      return new AutoValue_ToolchainResolverTest_ResolveToolchainsKey(
-          ImmutableSet.copyOf(requiredToolchains),
-          ImmutableSet.copyOf(execConstraintLabels),
-          configurationKey);
-    }
-  }
-
-  private EvaluationResult<ResolveToolchainsValue> createToolchainContextBuilder(
-      ResolveToolchainsKey key) throws InterruptedException {
-    try {
-      // Must re-enable analysis for Skyframe functions that create configured targets.
-      skyframeExecutor.getSkyframeBuildView().enableAnalysis(true);
-      return SkyframeExecutorTestUtils.evaluate(
-          skyframeExecutor, key, /*keepGoing=*/ false, reporter);
-    } finally {
-      skyframeExecutor.getSkyframeBuildView().enableAnalysis(false);
-    }
-  }
-
-  @AutoValue
-  abstract static class ResolveToolchainsValue implements SkyValue {
-    abstract UnloadedToolchainContext unloadedToolchainContext();
-
-    static ResolveToolchainsValue create(UnloadedToolchainContext unloadedToolchainContext) {
-      return new AutoValue_ToolchainResolverTest_ResolveToolchainsValue(unloadedToolchainContext);
-    }
-  }
-
-  private static final class ResolveToolchainsFunction implements SkyFunction {
-
-    @Nullable
-    @Override
-    public SkyValue compute(SkyKey skyKey, Environment env)
-        throws SkyFunctionException, InterruptedException {
-      ResolveToolchainsKey key = (ResolveToolchainsKey) skyKey;
-      ToolchainResolver toolchainResolver =
-          new ToolchainResolver(env, key.configurationKey())
-              .setRequiredToolchainTypes(key.requiredToolchainTypes())
-              .setExecConstraintLabels(key.execConstraintLabels());
-
-      try {
-        UnloadedToolchainContext unloadedToolchainContext = toolchainResolver.resolve();
-        if (unloadedToolchainContext == null) {
-          return null;
-        }
-        return ResolveToolchainsValue.create(unloadedToolchainContext);
-      } catch (ToolchainException e) {
-        throw new ResolveToolchainsFunctionException(e);
-      }
-    }
-
-    @Nullable
-    @Override
-    public String extractTag(SkyKey skyKey) {
-      return null;
-    }
-  }
-
-  private static class ResolveToolchainsFunctionException extends SkyFunctionException {
-    ResolveToolchainsFunctionException(ToolchainException e) {
-      super(e, Transience.PERSISTENT);
-    }
-  }
-}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java
index c99c79a..b267e88 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java
@@ -41,7 +41,6 @@
 import com.google.devtools.build.lib.analysis.ResolvedToolchainContext;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
-import com.google.devtools.build.lib.analysis.ToolchainResolver;
 import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
 import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
 import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
@@ -494,9 +493,13 @@
     SkyFunctionEnvironmentForTesting skyfunctionEnvironment =
         skyframeExecutor.getSkyFunctionEnvironmentForTesting(eventHandler);
     UnloadedToolchainContext unloadedToolchainContext =
-        new ToolchainResolver(skyfunctionEnvironment, BuildConfigurationValue.key(targetConfig))
-            .setRequiredToolchainTypes(requiredToolchains)
-            .resolve();
+        (UnloadedToolchainContext)
+            skyfunctionEnvironment.getValueOrThrow(
+                UnloadedToolchainContext.key()
+                    .configurationKey(BuildConfigurationValue.key(targetConfig))
+                    .requiredToolchainTypeLabels(requiredToolchains)
+                    .build(),
+                ToolchainException.class);
 
     OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap =
         getPrerequisiteMapForTesting(
diff --git a/src/test/shell/bazel/toolchain_test.sh b/src/test/shell/bazel/toolchain_test.sh
index 7eedb4e..44c6f24 100755
--- a/src/test/shell/bazel/toolchain_test.sh
+++ b/src/test/shell/bazel/toolchain_test.sh
@@ -441,7 +441,7 @@
     //demo:use &> $TEST_log || fail "Build failed"
   expect_log 'ToolchainResolution: Looking for toolchain of type //toolchain:test_toolchain'
   expect_log 'ToolchainResolution:   For toolchain type //toolchain:test_toolchain, possible execution platforms and toolchains: {@local_config_platform//:host -> //:test_toolchain_impl_1}'
-  expect_log 'ToolchainResolver: Selected execution platform @local_config_platform//:host, type //toolchain:test_toolchain -> toolchain //:test_toolchain_impl_1'
+  expect_log 'ToolchainResolution: Selected execution platform @local_config_platform//:host, type //toolchain:test_toolchain -> toolchain //:test_toolchain_impl_1'
   expect_log 'Using toolchain: rule message: "this is the rule", toolchain extra_str: "foo from test_toolchain"'
 }
 
@@ -820,7 +820,7 @@
     --extra_execution_platforms=//platform:test_platform \
     --toolchain_resolution_debug \
     //demo:target &> $TEST_log || fail "Build failed"
-  expect_log "ToolchainResolver: Selected execution platform //platform:test_platform"
+  expect_log "ToolchainResolution: Selected execution platform //platform:test_platform"
 }