Generalize ConfigSetting's special options handling.

Currently ConfigSetting is treated specially; TransitiveTargetFunction
identifies it by name, then runs a special function on it. This change
makes ConfigSetting use a new options reference function in RuleClass,
which TransitiveTargetFunction will evaluate over the rule and use with
the options-to-fragments map to figure out which fragments are needed.

Although this is still a hack and not really a new feature on RuleClass,
this avoids a dependency on ConfigSettingRule from TransitiveTargetFunction,
which is necessary for ConfigSettingRule to be moved to rules/config.

RELNOTES: None.

PiperOrigin-RevId: 152156905
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 1324cce..d8c06f5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -106,6 +106,8 @@
 public class RuleClass {
   static final Function<? super Rule, Map<String, Label>> NO_EXTERNAL_BINDINGS =
       Functions.<Map<String, Label>>constant(ImmutableMap.<String, Label>of());
+  static final Function<? super Rule, Set<String>> NO_OPTION_REFERENCE =
+      Functions.<Set<String>>constant(ImmutableSet.<String>of());
 
   public static final PathFragment THIRD_PARTY_PREFIX = PathFragment.create("third_party");
 
@@ -496,6 +498,8 @@
     private BaseFunction configuredTargetFunction = null;
     private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
         NO_EXTERNAL_BINDINGS;
+    private Function<? super Rule, ? extends Set<String>> optionReferenceFunction =
+        NO_OPTION_REFERENCE;
     @Nullable private Environment ruleDefinitionEnvironment = null;
     @Nullable private String ruleDefinitionEnvironmentHashCode = null;
     private ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
@@ -609,6 +613,7 @@
           advertisedProviders.build(),
           configuredTargetFunction,
           externalBindingsFunction,
+          optionReferenceFunction,
           ruleDefinitionEnvironment,
           ruleDefinitionEnvironmentHashCode,
           configurationFragmentPolicy.build(),
@@ -982,6 +987,18 @@
     }
 
     /**
+     * Causes rules of this type to implicitly reference the configuration fragments associated with
+     * the options its attributes reference.
+     *
+     * <p>This is only intended for use by {@code config_setting} - other rules should not use this!
+     */
+    public Builder setOptionReferenceFunctionForConfigSettingOnly(
+        Function<? super Rule, ? extends Set<String>> optionReferenceFunction) {
+      this.optionReferenceFunction = Preconditions.checkNotNull(optionReferenceFunction);
+      return this;
+    }
+
+    /**
      * Returns an Attribute.Builder object which contains a replica of the
      * same attribute in the parent rule if exists.
      *
@@ -1078,6 +1095,11 @@
   private final Function<? super Rule, Map<String, Label>> externalBindingsFunction;
 
   /**
+   * Returns the options referenced by this rule's attributes.
+   */
+  private final Function<? super Rule, ? extends Set<String>> optionReferenceFunction;
+
+  /**
    * The Skylark rule definition environment of this RuleClass.
    * Null for non Skylark executable RuleClasses.
    */
@@ -1138,6 +1160,7 @@
       AdvertisedProviderSet advertisedProviders,
       @Nullable BaseFunction configuredTargetFunction,
       Function<? super Rule, Map<String, Label>> externalBindingsFunction,
+      Function<? super Rule, ? extends Set<String>> optionReferenceFunction,
       @Nullable Environment ruleDefinitionEnvironment,
       String ruleDefinitionEnvironmentHashCode,
       ConfigurationFragmentPolicy configurationFragmentPolicy,
@@ -1161,6 +1184,7 @@
     this.advertisedProviders = advertisedProviders;
     this.configuredTargetFunction = configuredTargetFunction;
     this.externalBindingsFunction = externalBindingsFunction;
+    this.optionReferenceFunction = optionReferenceFunction;
     this.ruleDefinitionEnvironment = ruleDefinitionEnvironment;
     this.ruleDefinitionEnvironmentHashCode = ruleDefinitionEnvironmentHashCode;
     validateNoClashInPublicNames(attributes);
@@ -1924,6 +1948,13 @@
   }
 
   /**
+   * Returns a function that computes the options referenced by a rule.
+   */
+  public Function<? super Rule, ? extends Set<String>> getOptionReferenceFunction() {
+    return optionReferenceFunction;
+  }
+
+  /**
    * Returns this RuleClass's rule definition environment. Is null for native rules' RuleClass
    * objects and deserialized Skylark rules. Deserialized rules do provide a hash code encapsulating
    * their behavior, available at {@link #getRuleDefinitionEnvironmentHashCode}.