Make two LibraryToLinkWrapper$CcLinkingContext$LinkOptions value-equal if they have the same contents and were created by the same action owner at the same point in its analysis.

To do so, we expose an opaque SymbolGenerator in RuleContext/BazelStarlarkContext, as suggested by lberki@. The SymbolGenerator generates symbols (surprise) that will compare equal to other symbols that have the same "owner" (package, label, action lookup key, etc.) and index (order in which they were generated).

This is partially a logical rollback of https://github.com/bazelbuild/bazel/commit/830a286748f64e61dcb03c64318bc7e54cf87d88, with the symbol making things more acceptable.

PiperOrigin-RevId: 231848582
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index f1306a1..4e00092 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -34,6 +34,7 @@
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionLookupValue;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.ActionRegistry;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -56,6 +57,7 @@
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.analysis.skylark.SymbolGenerator;
 import com.google.devtools.build.lib.analysis.stringtemplate.TemplateContext;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
@@ -186,6 +188,7 @@
   private final ConstraintSemantics constraintSemantics;
 
   private ActionOwner actionOwner;
+  private final SymbolGenerator<ActionLookupValue.ActionLookupKey> actionOwnerSymbolGenerator;
 
   /* lazily computed cache for Make variables, computed from the above. See get... method */
   private transient ConfigurationMakeVariableContext configurationMakeVariableContext = null;
@@ -196,8 +199,9 @@
       ListMultimap<String, ConfiguredTargetAndData> targetMap,
       ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
-      ImmutableList<Class<? extends BuildConfiguration.Fragment>> universalFragments,
+      ImmutableList<Class<? extends Fragment>> universalFragments,
       String ruleClassNameForLogging,
+      ActionLookupValue.ActionLookupKey actionLookupKey,
       ImmutableMap<String, Attribute> aspectAttributes,
       @Nullable ToolchainContext toolchainContext,
       ConstraintSemantics constraintSemantics) {
@@ -228,6 +232,7 @@
     this.disabledFeatures = ImmutableSortedSet.copyOf(allDisabledFeatures);
     this.ruleClassNameForLogging = ruleClassNameForLogging;
     this.hostConfiguration = builder.hostConfiguration;
+    this.actionOwnerSymbolGenerator = new SymbolGenerator<>(actionLookupKey);
     reporter = builder.reporter;
     this.toolchainContext = toolchainContext;
     this.constraintSemantics = constraintSemantics;
@@ -409,6 +414,16 @@
   }
 
   /**
+   * An opaque symbol generator to be used when identifying objects by their action owner/index of
+   * creation. Only needed if an object needs to know whether it was created by the same action
+   * owner in the same order as another object. Each symbol must call {@link
+   * SymbolGenerator#generate} separately to obtain a unique object.
+   */
+  public SymbolGenerator<?> getSymbolGenerator() {
+    return actionOwnerSymbolGenerator;
+  }
+
+  /**
    * Returns a configuration fragment for this this target.
    */
   @Nullable
@@ -1447,7 +1462,6 @@
   /**
    * Builder class for a RuleContext.
    */
-  @VisibleForTesting
   public static final class Builder implements RuleErrorConsumer  {
     private final AnalysisEnvironment env;
     private final Target target;
@@ -1455,6 +1469,7 @@
     private ImmutableList<Class<? extends BuildConfiguration.Fragment>> universalFragments;
     private final BuildConfiguration configuration;
     private final BuildConfiguration hostConfiguration;
+    private final ActionLookupValue.ActionLookupKey actionOwnerSymbol;
     private final PrerequisiteValidator prerequisiteValidator;
     private final RuleErrorConsumer reporter;
     private OrderedSetMultimap<Attribute, ConfiguredTargetAndData> prerequisiteMap;
@@ -1473,7 +1488,8 @@
         BuildConfiguration configuration,
         BuildConfiguration hostConfiguration,
         PrerequisiteValidator prerequisiteValidator,
-        ConfigurationFragmentPolicy configurationFragmentPolicy) {
+        ConfigurationFragmentPolicy configurationFragmentPolicy,
+        ActionLookupValue.ActionLookupKey actionOwnerSymbol) {
       this.env = Preconditions.checkNotNull(env);
       this.target = Preconditions.checkNotNull(target);
       this.aspects = aspects;
@@ -1481,6 +1497,7 @@
       this.configuration = Preconditions.checkNotNull(configuration);
       this.hostConfiguration = Preconditions.checkNotNull(hostConfiguration);
       this.prerequisiteValidator = prerequisiteValidator;
+      this.actionOwnerSymbol = Preconditions.checkNotNull(actionOwnerSymbol);
       if (configuration.allowAnalysisFailures()) {
         reporter = new SuppressingErrorReporter();
       } else {
@@ -1508,6 +1525,7 @@
           configConditions,
           universalFragments,
           getRuleClassNameForLogging(),
+          actionOwnerSymbol,
           aspectAttributes != null ? aspectAttributes : ImmutableMap.<String, Attribute>of(),
           toolchainContext,
           constraintSemantics);