Deprecate TransitiveInfoCollection#getConfiguration(), adding two new methods, TransitiveInfoCollection#getConfigurationKey() and ConfiguredTarget#getConfigurationChecksum(). These methods currently delegate to #getConfiguration(), but in the future they won't. I hope to get rid of #getConfigurationChecksum(), but I may have to fold the checksum into BuildConfigurationValue.Key or leave it as a separate field in ConfiguredTarget.

Transform a representative (random?) selection of #getConfiguration calls, to show that it's pretty much possible everywhere.

PiperOrigin-RevId: 190474978
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index deaddcb..cd94353 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -81,6 +81,7 @@
 import com.google.devtools.build.lib.skyframe.AspectValue;
 import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
 import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
+import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
 import com.google.devtools.build.lib.skyframe.CoverageReportValue;
@@ -613,7 +614,10 @@
     }
 
     Set<ConfiguredTarget> targetsToSkip =
-        new TopLevelConstraintSemantics(skyframeExecutor.getPackageManager(), eventHandler)
+        new TopLevelConstraintSemantics(
+                skyframeExecutor.getPackageManager(),
+                input -> skyframeExecutor.getConfiguration(eventHandler, input),
+                eventHandler)
             .checkTargetEnvironmentRestrictions(skyframeAnalysisResult.getConfiguredTargets());
 
     AnalysisResult result =
@@ -975,7 +979,7 @@
           throws EvalException, InvalidConfigurationException, InterruptedException,
               InconsistentAspectOrderException {
     return getConfiguredTargetAndDataDirectPrerequisitesForTesting(
-        eventHandler, ct, ct.getConfiguration(), configurations);
+        eventHandler, ct, ct.getConfigurationKey(), configurations);
   }
 
   @VisibleForTesting
@@ -987,14 +991,17 @@
           throws EvalException, InvalidConfigurationException, InterruptedException,
               InconsistentAspectOrderException {
     return getConfiguredTargetAndDataDirectPrerequisitesForTesting(
-        eventHandler, ct.getConfiguredTarget(), ct.getConfiguration(), configurations);
+        eventHandler,
+        ct.getConfiguredTarget(),
+        ct.getConfiguredTarget().getConfigurationKey(),
+        configurations);
   }
 
   private Collection<ConfiguredTargetAndData>
       getConfiguredTargetAndDataDirectPrerequisitesForTesting(
           ExtendedEventHandler eventHandler,
           ConfiguredTarget ct,
-          BuildConfiguration configuration,
+          BuildConfigurationValue.Key configuration,
           BuildConfigurationCollection configurations)
           throws EvalException, InvalidConfigurationException, InterruptedException,
               InconsistentAspectOrderException {
@@ -1066,7 +1073,7 @@
           Iterable<BuildOptions> buildOptions,
           BuildOptions defaultBuildOptions) {
         Preconditions.checkArgument(
-            ct.getConfiguration().fragmentClasses().equals(fragments),
+            fragments.fragmentClasses().equals(ct.getConfigurationKey().getFragments()),
             "Mismatch: %s %s",
             ct,
             fragments);
@@ -1085,7 +1092,9 @@
     }
 
     DependencyResolver dependencyResolver = new SilentDependencyResolver();
-    TargetAndConfiguration ctgNode = new TargetAndConfiguration(target, ct.getConfiguration());
+    TargetAndConfiguration ctgNode =
+        new TargetAndConfiguration(
+            target, skyframeExecutor.getConfiguration(eventHandler, ct.getConfigurationKey()));
     return dependencyResolver.dependentNodeMap(
         ctgNode,
         configurations.getHostConfiguration(),
@@ -1135,7 +1144,7 @@
 
     ImmutableMultimap<Dependency, ConfiguredTargetAndData> cts =
         skyframeExecutor.getConfiguredTargetMapForTesting(
-            eventHandler, target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()));
+            eventHandler, target.getConfigurationKey(), ImmutableSet.copyOf(depNodeNames.values()));
 
     OrderedSetMultimap<Attribute, ConfiguredTargetAndData> result = OrderedSetMultimap.create();
     for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
index b44dfd0..c7c0866 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
@@ -55,6 +55,10 @@
   @Nullable
   BuildConfiguration getConfiguration();
 
+  default String getConfigurationChecksum() {
+    return getConfiguration().checksum();
+  }
+
   /**
    * Returns keys for a legacy Skylark provider.
    *
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
index 0727e22..a2e3734 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
@@ -16,11 +16,14 @@
 
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.configuredtargets.InputFileConfiguredTarget;
+import com.google.devtools.build.lib.analysis.configuredtargets.PackageGroupConfiguredTarget;
 import com.google.devtools.build.lib.cmdline.Label;
 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 com.google.devtools.build.lib.packages.RequiredProviders;
+import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
 import com.google.devtools.build.lib.skylarkinterface.Param;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
@@ -94,13 +97,25 @@
    */
   Label getLabel();
 
+  /** Deprecated! Use {@link #getConfigurationKey} instead. */
+  @Deprecated
+  @Nullable
+  BuildConfiguration getConfiguration();
+
   /**
-   * <p>Returns the {@link BuildConfiguration} for which this transitive info collection is defined.
-   * Configuration is defined for all configured targets with exception of {@link
-   * InputFileConfiguredTarget} and {@link PackageGroupConfiguredTarget} for which it is always
-   * <b>null</b>.</p>
+   * Returns the {@link BuildConfigurationValue.Key} naming the {@link BuildConfiguration} for which
+   * this transitive info collection is defined. Configuration is defined for all configured targets
+   * with exception of {@link InputFileConfiguredTarget} and {@link PackageGroupConfiguredTarget}
+   * for which it is always <b>null</b>.
    */
-  @Nullable BuildConfiguration getConfiguration();
+  @Nullable
+  default BuildConfigurationValue.Key getConfigurationKey() {
+    BuildConfiguration configuration = getConfiguration();
+    return configuration == null
+        ? null
+        : BuildConfigurationValue.key(
+            configuration.fragmentClasses(), configuration.getBuildOptionsDiff());
+  }
 
   /**
    * Checks whether this {@link TransitiveInfoCollection} satisfies given {@link RequiredProviders}.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
index 825ba5a..9bd4119 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
@@ -89,7 +89,7 @@
 
   @Override
   public String toString() {
-    return "ConfiguredTarget(" + getLabel() + ", " + getConfiguration() + ")";
+    return "ConfiguredTarget(" + getLabel() + ", " + getConfigurationChecksum() + ")";
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
index 42397c0..0cae3d3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
@@ -54,7 +54,7 @@
   public InputFileConfiguredTarget(
       TargetContext targetContext, InputFile inputFile, Artifact artifact) {
     this(inputFile.getLabel(), targetContext.getVisibility(), artifact, makeLicenses(inputFile));
-    Preconditions.checkArgument(getConfiguration() == null, getLabel());
+    Preconditions.checkArgument(getConfigurationKey() == null, getLabel());
     Preconditions.checkArgument(targetContext.getTarget() == inputFile, getLabel());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java b/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java
index 4e1f099..130d4ef 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java
@@ -34,10 +34,12 @@
 import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.pkgcache.PackageManager;
+import com.google.devtools.build.lib.skyframe.BuildConfigurationValue.Key;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 
@@ -51,17 +53,21 @@
  */
 public class TopLevelConstraintSemantics {
   private final PackageManager packageManager;
+  private final Function<Key, BuildConfiguration> configurationProvider;
   private final ExtendedEventHandler eventHandler;
 
   /**
    * Constructor with helper classes for loading targets.
    *
-  * @param packageManager object for retrieving loaded targets
-  * @param eventHandler the build's event handler
-  */
-  public TopLevelConstraintSemantics(PackageManager packageManager,
+   * @param packageManager object for retrieving loaded targets
+   * @param eventHandler the build's event handler
+   */
+  public TopLevelConstraintSemantics(
+      PackageManager packageManager,
+      Function<Key, BuildConfiguration> configurationProvider,
       ExtendedEventHandler eventHandler) {
     this.packageManager = packageManager;
+    this.configurationProvider = configurationProvider;
     this.eventHandler = eventHandler;
   }
 
@@ -84,7 +90,7 @@
    *     environment declared through {@link BuildConfiguration.Options#targetEnvironments}
    */
   public Set<ConfiguredTarget> checkTargetEnvironmentRestrictions(
-      Iterable<ConfiguredTarget> topLevelTargets)
+      ImmutableList<ConfiguredTarget> topLevelTargets)
       throws ViewCreationFailedException, InterruptedException {
     ImmutableSet.Builder<ConfiguredTarget> badTargets = ImmutableSet.builder();
     // Maps targets that are missing *explicitly* required environments to the set of environments
@@ -93,7 +99,7 @@
     // continues while skipping them.
     Multimap<ConfiguredTarget, Label> exceptionInducingTargets = ArrayListMultimap.create();
     for (ConfiguredTarget topLevelTarget : topLevelTargets) {
-      BuildConfiguration config = topLevelTarget.getConfiguration();
+      BuildConfiguration config = configurationProvider.apply(topLevelTarget.getConfigurationKey());
       Target target = null;
       try {
         target = packageManager.getTarget(eventHandler, topLevelTarget.getLabel());