Allow accessing the configuration of a dependency during resolution.

This is necessary because with trimming, the configuration that a configured
target was analyzed with may not be the configuration that it was requested
with.

Progress on #6524.

PiperOrigin-RevId: 244209432
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 fd9e90e..854ffe3 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
@@ -736,12 +736,32 @@
               }
             }
             try {
+              BuildConfiguration depConfiguration = dep.getConfiguration();
+              BuildConfigurationValue.Key depKey =
+                  depValue.getConfiguredTarget().getConfigurationKey();
+              // Retroactive trimming may change the configuration associated with the dependency.
+              // If it does, we need to get that instance.
+              // TODO(mstaib): doing these individually instead of doing them all at once may end up
+              // being wasteful use of Skyframe. Although these configurations are guaranteed to be
+              // in the Skyframe cache (because the dependency would have had to retrieve them to be
+              // created in the first place), looking them up repeatedly may be slower than just
+              // keeping a local cache and assigning the same configuration to all the CTs which
+              // need it. Profile this and see if there's a better way.
+              if (depKey != null && !depKey.equals(BuildConfigurationValue.key(depConfiguration))) {
+                if (!depConfiguration.trimConfigurationsRetroactively()) {
+                  throw new AssertionError(
+                      "Loading configurations mid-dependency resolution should ONLY happen when "
+                          + "retroactive trimming is enabled.");
+                }
+                depConfiguration =
+                    ((BuildConfigurationValue) env.getValue(depKey)).getConfiguration();
+              }
               result.put(
                   key,
                   new ConfiguredTargetAndData(
                       depValue.getConfiguredTarget(),
                       pkgValue.getPackage().getTarget(depLabel.getName()),
-                      dep.getConfiguration()));
+                      depConfiguration));
             } catch (NoSuchTargetException e) {
               throw new IllegalStateException("Target already verified for " + dep, e);
             }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index 0298f62..eadebad 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -1739,15 +1739,34 @@
           try {
             ConfiguredTarget mergedTarget =
                 MergedConfiguredTarget.of(configuredTarget, configuredAspects);
+            BuildConfigurationValue.Key configKey = mergedTarget.getConfigurationKey();
+            BuildConfiguration resolvedConfig = depConfig;
+            if (configKey == null) {
+              // Unfortunately, it's possible to get a configured target with a null configuration
+              // when depConfig is non-null, so we need to explicitly override it in that case.
+              resolvedConfig = null;
+            } else if (!configKey.equals(BuildConfigurationValue.key(depConfig))) {
+              // Retroactive trimming may change the configuration associated with the dependency.
+              // If it does, we need to get that instance.
+              // TODO(mstaib): doing these individually instead of doing them all at once may end
+              // up being wasteful use of Skyframe. Although these configurations are guaranteed
+              // to be in the Skyframe cache (because the dependency would have had to retrieve
+              // them to be created in the first place), looking them up repeatedly may be slower
+              // than just keeping a local cache and assigning the same configuration to all the
+              // CTs which need it. Profile this and see if there's a better way.
+              if (!depConfig.trimConfigurationsRetroactively()) {
+                throw new AssertionError(
+                    "Loading configurations mid-dependency resolution should ONLY happen when "
+                        + "retroactive trimming is enabled.");
+              }
+              resolvedConfig = getConfiguration(eventHandler, mergedTarget.getConfigurationKey());
+            }
             cts.put(
                 key,
                 new ConfiguredTargetAndData(
                     mergedTarget,
                     packageValue.getPackage().getTarget(configuredTarget.getLabel().getName()),
-                    // This is terrible, but our tests' use of configurations is terrible. It's only
-                    // by accident that getting a null-configuration ConfiguredTarget works even if
-                    // depConfig is not null.
-                    mergedTarget.getConfigurationKey() == null ? null : depConfig));
+                    resolvedConfig));
 
           } catch (DuplicateException | NoSuchTargetException e) {
             throw new IllegalStateException(