// Copyright 2014 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.starlark;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.devtools.build.lib.analysis.BaseRuleClasses.RUN_UNDER;
import static com.google.devtools.build.lib.analysis.BaseRuleClasses.TIMEOUT_DEFAULT;
import static com.google.devtools.build.lib.analysis.BaseRuleClasses.getTestRuntimeLabelList;
import static com.google.devtools.build.lib.analysis.test.ExecutionInfo.DEFAULT_TEST_RUNNER_EXEC_GROUP;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.LICENSE;
import static com.google.devtools.build.lib.packages.BuiltinRestriction.allowlistEntry;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.analysis.Allowlist;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.config.transitions.ComposingTransitionFactory;
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
import com.google.devtools.build.lib.analysis.config.transitions.StarlarkExposedRuleTransitionFactory;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.starlark.StarlarkAttrModule.Descriptor;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.cmdline.BazelModuleContext;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.AllowlistChecker;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate;
import com.google.devtools.build.lib.packages.AttributeTransitionData;
import com.google.devtools.build.lib.packages.AttributeValueSource;
import com.google.devtools.build.lib.packages.BazelStarlarkContext;
import com.google.devtools.build.lib.packages.BuildSetting;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.BuiltinRestriction;
import com.google.devtools.build.lib.packages.BuiltinRestriction.AllowlistEntry;
import com.google.devtools.build.lib.packages.BzlInitThreadContext;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
import com.google.devtools.build.lib.packages.ExecGroup;
import com.google.devtools.build.lib.packages.FunctionSplitTransitionAllowlist;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.StarlarkImplicitOutputsFunctionWithCallback;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.StarlarkImplicitOutputsFunctionWithMap;
import com.google.devtools.build.lib.packages.LabelConverter;
import com.google.devtools.build.lib.packages.Package.NameConflictException;
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
import com.google.devtools.build.lib.packages.PredicateWithMessage;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.RuleFactory;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
import com.google.devtools.build.lib.packages.RuleFunction;
import com.google.devtools.build.lib.packages.RuleTransitionData;
import com.google.devtools.build.lib.packages.StarlarkAspect;
import com.google.devtools.build.lib.packages.StarlarkCallbackHelper;
import com.google.devtools.build.lib.packages.StarlarkDefinedAspect;
import com.google.devtools.build.lib.packages.StarlarkExportable;
import com.google.devtools.build.lib.packages.StarlarkProvider;
import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.starlarkbuildapi.StarlarkRuleFunctionsApi;
import com.google.devtools.build.lib.starlarkbuildapi.StarlarkSubruleApi;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.Pair;
import com.google.errorprone.annotations.FormatMethod;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkCallable;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.Tuple;
import net.starlark.java.syntax.Identifier;
import net.starlark.java.syntax.Location;

/** A helper class to provide an easier API for Starlark rule definitions. */
public class StarlarkRuleClassFunctions implements StarlarkRuleFunctionsApi {
  // A cache for base rule classes (especially tests).
  private static final LoadingCache<String, Label> labelCache =
      Caffeine.newBuilder().build(Label::parseCanonical);

  // TODO(bazel-team): Remove the code duplication (BaseRuleClasses and this class).
  /** Parent rule class for non-executable non-test Starlark rules. */
  public static final RuleClass baseRule =
      BaseRuleClasses.commonCoreAndStarlarkAttributes(
              new RuleClass.Builder("$base_rule", RuleClassType.ABSTRACT, true)
                  .add(attr("expect_failure", STRING)))
          // TODO(skylark-team): Allow Starlark rules to extend native rules and remove duplication.
          .add(
              attr("toolchains", LABEL_LIST)
                  .allowedFileTypes(FileTypeSet.NO_FILE)
                  .mandatoryProviders(ImmutableList.of(TemplateVariableInfo.PROVIDER.id()))
                  .dontCheckConstraints())
          .add(attr(RuleClass.EXEC_PROPERTIES_ATTR, Type.STRING_DICT).value(ImmutableMap.of()))
          .add(
              attr(RuleClass.EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST)
                  .allowedFileTypes()
                  .nonconfigurable("Used in toolchain resolution")
                  .tool(
                      "exec_compatible_with exists for constraint checking, not to create an"
                          + " actual dependency")
                  .value(ImmutableList.of()))
          .add(
              attr(RuleClass.TARGET_COMPATIBLE_WITH_ATTR, LABEL_LIST)
                  .mandatoryProviders(ConstraintValueInfo.PROVIDER.id())
                  // This should be configurable to allow for complex types of restrictions.
                  .tool(
                      "target_compatible_with exists for constraint checking, not to create an"
                          + " actual dependency")
                  .allowedFileTypes(FileTypeSet.NO_FILE))
          .build();

  /** Parent rule class for executable non-test Starlark rules. */
  private static final RuleClass binaryBaseRule =
      new RuleClass.Builder("$binary_base_rule", RuleClassType.ABSTRACT, true, baseRule)
          .add(attr("args", STRING_LIST))
          .add(attr("output_licenses", LICENSE))
          .addAttribute(
              attr("$is_executable", BOOLEAN)
                  .value(true)
                  .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target")
                  .build())
          .build();

  public static final ImmutableSet<AllowlistEntry> ALLOWLIST_RULE_EXTENSION_API =
      ImmutableSet.of(
          allowlistEntry("", "initializer_testing"),
          allowlistEntry("", "extend_rule_testing"),
          allowlistEntry("", "subrule_testing"));

  public static final ImmutableSet<AllowlistEntry> ALLOWLIST_RULE_EXTENSION_API_EXPERIMENTAL =
      ImmutableSet.of(allowlistEntry("", "initializer_testing/builtins"));

  /** Parent rule class for test Starlark rules. */
  public static RuleClass getTestBaseRule(RuleDefinitionEnvironment env) {
    RepositoryName toolsRepository = env.getToolsRepository();
    RuleClass.Builder builder =
        new RuleClass.Builder("$test_base_rule", RuleClassType.ABSTRACT, true, baseRule)
            .requiresConfigurationFragments(TestConfiguration.class)
            // TestConfiguration only needed to create TestAction and TestProvider
            // Only necessary at top-level and can be skipped if trimmed.
            .setMissingFragmentPolicy(TestConfiguration.class, MissingFragmentPolicy.IGNORE)
            .add(
                attr("size", STRING)
                    .value("medium")
                    .taggable()
                    .nonconfigurable("used in loading phase rule validation logic"))
            .add(
                attr("timeout", STRING)
                    .taggable()
                    .nonconfigurable("policy decision: should be consistent across configurations")
                    .value(TIMEOUT_DEFAULT))
            .add(
                attr("flaky", BOOLEAN)
                    .value(false)
                    .taggable()
                    .nonconfigurable("taggable - called in Rule.getRuleTags"))
            .add(attr("shard_count", INTEGER).value(StarlarkInt.of(-1)))
            .add(
                attr("local", BOOLEAN)
                    .value(false)
                    .taggable()
                    .nonconfigurable(
                        "policy decision: this should be consistent across configurations"))
            .add(attr("args", STRING_LIST))
            // Input files for every test action
            .add(
                attr("$test_wrapper", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .singleArtifact()
                    .value(labelCache.get(toolsRepository + "//tools/test:test_wrapper")))
            .add(
                attr("$xml_writer", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .singleArtifact()
                    .value(labelCache.get(toolsRepository + "//tools/test:xml_writer")))
            .add(
                attr("$test_runtime", LABEL_LIST)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    // Getting this default value through the getTestRuntimeLabelList helper ensures
                    // we reuse the same ImmutableList<Label> instance for each $test_runtime attr.
                    .value(getTestRuntimeLabelList(env)))
            .add(
                attr("$test_setup_script", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .singleArtifact()
                    .value(labelCache.get(toolsRepository + "//tools/test:test_setup")))
            .add(
                attr("$xml_generator_script", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .singleArtifact()
                    .value(labelCache.get(toolsRepository + "//tools/test:test_xml_generator")))
            .add(
                attr("$collect_coverage_script", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .singleArtifact()
                    .value(labelCache.get(toolsRepository + "//tools/test:collect_coverage")))
            // Input files for test actions collecting code coverage
            .add(
                attr(":coverage_support", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .value(
                        BaseRuleClasses.coverageSupportAttribute(
                            labelCache.get(
                                toolsRepository + BaseRuleClasses.DEFAULT_COVERAGE_SUPPORT_VALUE))))
            // Used in the one-per-build coverage report generation action.
            .add(
                attr(":coverage_report_generator", LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .value(
                        BaseRuleClasses.coverageReportGeneratorAttribute(
                            labelCache.get(
                                toolsRepository
                                    + BaseRuleClasses.DEFAULT_COVERAGE_REPORT_GENERATOR_VALUE))))
            .add(attr(":run_under", LABEL).value(RUN_UNDER))
            .addAttribute(
                attr("$is_executable", BOOLEAN)
                    .value(true)
                    .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target")
                    .build());

    env.getNetworkAllowlistForTests()
        .ifPresent(
            label ->
                builder.add(
                    Allowlist.getAttributeFromAllowlistName("external_network").value(label)));

    return builder.build();
  }

  @Override
  public Object provider(Object doc, Object fields, Object init, StarlarkThread thread)
      throws EvalException {
    StarlarkProvider.Builder builder = StarlarkProvider.builder(thread.getCallerLocation());
    Starlark.toJavaOptional(doc, String.class)
        .map(Starlark::trimDocString)
        .ifPresent(builder::setDocumentation);
    if (fields instanceof Sequence) {
      builder.setSchema(Sequence.cast(fields, String.class, "fields"));
    } else if (fields instanceof Dict) {
      builder.setSchema(
          Maps.transformValues(
              Dict.cast(fields, String.class, String.class, "fields"), Starlark::trimDocString));
    }
    if (init == Starlark.NONE) {
      return builder.build();
    } else {
      if (init instanceof StarlarkCallable) {
        builder.setInit((StarlarkCallable) init);
      } else {
        throw Starlark.errorf("got %s for init, want callable value", Starlark.type(init));
      }
      StarlarkProvider provider = builder.build();
      return Tuple.of(provider, provider.createRawConstructor());
    }
  }

  @FormatMethod
  private static void failIf(boolean condition, String message, Object... args)
      throws EvalException {
    if (condition) {
      throw Starlark.errorf(message, args);
    }
  }

  // TODO(bazel-team): implement attribute copy and other rule properties
  @Override
  public StarlarkRuleFunction rule(
      StarlarkFunction implementation,
      Object testUnchecked,
      Dict<?, ?> attrs,
      Object implicitOutputs,
      Object executableUnchecked,
      boolean outputToGenfiles,
      Sequence<?> fragments,
      Sequence<?> hostFragments,
      boolean starlarkTestable,
      Sequence<?> toolchains,
      boolean useToolchainTransition,
      Object doc,
      Sequence<?> providesArg,
      Sequence<?> execCompatibleWith,
      boolean analysisTest,
      Object buildSetting,
      Object cfg,
      Object execGroups,
      Object initializer,
      Object parentUnchecked,
      Object extendableUnchecked,
      Sequence<?> subrules,
      StarlarkThread thread)
      throws EvalException {
    // Ensure we're initializing a .bzl file, which also means we have a RuleDefinitionEnvironment.
    BzlInitThreadContext bazelContext = BzlInitThreadContext.fromOrFail(thread, "rule()");

    if (initializer != Starlark.NONE
        || parentUnchecked != Starlark.NONE
        || !subrules.isEmpty()
        || extendableUnchecked != Starlark.NONE) {
      if (!thread.getSemantics().getBool(BuildLanguageOptions.EXPERIMENTAL_RULE_EXTENSION_API)) {
        BuiltinRestriction.failIfCalledOutsideAllowlist(thread, ALLOWLIST_RULE_EXTENSION_API);
      }
    }

    final RuleClass parent;
    final boolean executable;
    final boolean test;

    if (parentUnchecked == Starlark.NONE) {
      parent = null;
      executable = executableUnchecked == Starlark.UNBOUND ? false : (Boolean) executableUnchecked;
      test = testUnchecked == Starlark.UNBOUND ? false : (Boolean) testUnchecked;
    } else {
      failIf(
          !(parentUnchecked instanceof StarlarkRuleFunction), "Parent needs to be a Starlark rule");
      // Assuming parent is already exported.
      failIf(
          ((StarlarkRuleFunction) parentUnchecked).ruleClass == null,
          "Please export the parent rule before extending it.");

      parent = ((StarlarkRuleFunction) parentUnchecked).ruleClass;
      executable = parent.isExecutableStarlark();
      test = parent.getRuleClassType() == RuleClassType.TEST;

      failIf(
          !parent.isExtendable(),
          "The rule '%s' is not extendable. Only Starlark rules not using deprecated features (like"
              + " implicit outputs, output to genfiles) may be extended. Special rules like"
              + " analysis tests or rules using build_settings cannot be extended.",
          parent.getName());

      failIf(
          executableUnchecked != Starlark.UNBOUND,
          "Omit executable parameter when extending rules.");
      failIf(testUnchecked != Starlark.UNBOUND, "Omit test parameter when extending rules.");
      failIf(
          implicitOutputs != Starlark.NONE,
          "implicit_outputs is not supported when extending rules (deprecated).");
      failIf(
          !hostFragments.isEmpty(),
          "host_fragments are not supported when extending rules (deprecated).");
      failIf(
          outputToGenfiles,
          "output_to_genfiles are not supported when extending rules (deprecated).");
      failIf(starlarkTestable, "_skylark_testable is not supported when extending rules.");
      failIf(analysisTest, "analysis_test is not supported when extending rules.");
      failIf(buildSetting != Starlark.NONE, "build_setting is not supported when extending rules.");
    }

    // Get the callstack, sans the last entry, which is the builtin 'rule' callable itself.
    ImmutableList<StarlarkThread.CallStackEntry> callStack = thread.getCallStack();
    callStack = callStack.subList(0, callStack.size() - 1);

    LabelConverter labelConverter = LabelConverter.forBzlEvaluatingThread(thread);

    return createRule(
        // Contextual parameters.
        bazelContext,
        thread.getCallerLocation(),
        callStack,
        bazelContext.getBzlFile(),
        bazelContext.getTransitiveDigest(),
        labelConverter,
        thread.getSemantics(),
        // rule() parameters
        parent,
        extendableUnchecked,
        implementation,
        initializer == Starlark.NONE ? null : (StarlarkFunction) initializer,
        test,
        attrs,
        implicitOutputs,
        executable,
        outputToGenfiles,
        fragments,
        starlarkTestable,
        toolchains,
        doc,
        providesArg,
        execCompatibleWith,
        analysisTest,
        buildSetting,
        cfg,
        execGroups,
        subrules);
  }

  /**
   * Returns a new function representing a Starlark-defined rule.
   *
   * <p>This is public for the benefit of {@link StarlarkTestingModule}, which has the unusual use
   * case of creating new rule types to house analysis-time test assertions ({@code analysis_test}).
   * It's probably not a good idea to add new callers of this method.
   *
   * <p>Note that the bzlFile and transitiveDigest params correspond to the outermost .bzl file
   * being evaluated, not the one in which rule() is called.
   */
  public static StarlarkRuleFunction createRule(
      // Contextual parameters.
      RuleDefinitionEnvironment ruleDefinitionEnvironment,
      Location loc,
      ImmutableList<StarlarkThread.CallStackEntry> definitionCallstack,
      Label bzlFile,
      byte[] transitiveDigest,
      LabelConverter labelConverter,
      StarlarkSemantics starlarkSemantics,
      // Parameters that come from rule().
      @Nullable RuleClass parent,
      @Nullable Object extendableUnchecked,
      StarlarkFunction implementation,
      @Nullable StarlarkFunction initializer,
      boolean test,
      Dict<?, ?> attrs,
      Object implicitOutputs,
      boolean executable,
      boolean outputToGenfiles,
      Sequence<?> fragments,
      boolean starlarkTestable,
      Sequence<?> toolchains,
      Object doc,
      Sequence<?> providesArg,
      Sequence<?> execCompatibleWith,
      Object analysisTest,
      Object buildSetting,
      Object cfg,
      Object execGroups,
      Sequence<?> subrulesUnchecked)
      throws EvalException {

    // analysis_test=true implies test=true.
    test |= Boolean.TRUE.equals(analysisTest);

    RuleClassType type = test ? RuleClassType.TEST : RuleClassType.NORMAL;

    final RuleClass.Builder builder;
    if (parent != null) {
      // We'll set the name later, pass the empty string for now.
      builder = new RuleClass.Builder("", type, true, parent);
    } else {
      // We'll set the name later, pass the empty string for now.
      RuleClass baseParent =
          test
              ? getTestBaseRule(ruleDefinitionEnvironment)
              : (executable ? binaryBaseRule : baseRule);
      builder = new RuleClass.Builder("", type, true, baseParent);
    }

    builder.initializer(initializer, labelConverter);

    builder.setDefaultExtendableAllowlist(
        ruleDefinitionEnvironment.getToolsLabel("//tools/allowlists/extend_rule_allowlist"));
    if (extendableUnchecked instanceof Boolean) {
      builder.setExtendable((Boolean) extendableUnchecked);
    } else if (extendableUnchecked instanceof String) {
      try {
        builder.setExtendableByAllowlist(labelConverter.convert((String) extendableUnchecked));
      } catch (LabelSyntaxException e) {
        throw Starlark.errorf(
            "Unable to parse label '%s': %s", extendableUnchecked, e.getMessage());
      }
    } else if (extendableUnchecked instanceof Label) {
      builder.setExtendableByAllowlist((Label) extendableUnchecked);
    } else {
      failIf(
          !(extendableUnchecked == Starlark.NONE || extendableUnchecked == null),
          "parameter 'extendable': expected bool, str or Label, but got '%s'",
          Starlark.type(extendableUnchecked));
    }

    // Verify the child against parent's allowlist
    if (parent != null && parent.getExtendableAllowlist() != null) {
      builder.addAllowlistChecker(EXTEND_RULE_ALLOWLIST_CHECKER);
      Attribute.Builder<Label> allowlistAttr =
          attr("$allowlist_extend_rule", LABEL)
              .cfg(ExecutionTransitionFactory.createFactory())
              .mandatoryBuiltinProviders(ImmutableList.of(PackageSpecificationProvider.class))
              .value(parent.getExtendableAllowlist());
      if (builder.contains("$allowlist_extend_rule")) {
        // the allowlist already exist if this is the second extension of the rule
        // in this case we need to override the allowlist with the one in the direct parent
        builder.override(allowlistAttr);
      } else {
        builder.add(allowlistAttr);
      }
    }

    if (executable || test) {
      builder.setExecutableStarlark();
    }

    builder.setCallStack(definitionCallstack);

    ImmutableList<Pair<String, StarlarkAttrModule.Descriptor>> attributes =
        attrObjectToAttributesList(attrs);

    if (starlarkTestable) {
      builder.setStarlarkTestable();
    }
    if (Boolean.TRUE.equals(analysisTest)) {
      builder.setIsAnalysisTest();
    }

    boolean hasStarlarkDefinedTransition = false;
    for (Pair<String, StarlarkAttrModule.Descriptor> attribute : attributes) {
      String name = attribute.getFirst();
      StarlarkAttrModule.Descriptor descriptor = attribute.getSecond();

      Attribute attr = descriptor.build(name);

      hasStarlarkDefinedTransition |= attr.hasStarlarkDefinedTransition();
      if (attr.hasAnalysisTestTransition()) {
        if (!builder.isAnalysisTest()) {
          throw Starlark.errorf(
              "Only rule definitions with analysis_test=True may have attributes with"
                  + " analysis_test_transition transitions");
        }
        builder.setHasAnalysisTestTransition();
      }

      try {
        if (builder.contains(attr.getName())) {
          builder.override(attr);
        } else {
          builder.addAttribute(attr);
        }
      } catch (IllegalStateException ex) {
        // TODO(bazel-team): stop using unchecked exceptions in this way.
        throw Starlark.errorf("cannot add attribute: %s", ex.getMessage());
      }
    }

    // the set of subrules is stored in the rule class, primarily for validating that a rule class
    // declared the subrule when using it.
    ImmutableList<StarlarkSubrule> subrules =
        Sequence.cast(subrulesUnchecked, StarlarkSubrule.class, "subrules").getImmutableList();
    builder.addToolchainTypes(StarlarkSubrule.discoverToolchains(subrules));
    builder.setSubrules(subrules);

    if (implicitOutputs != Starlark.NONE) {
      if (implicitOutputs instanceof StarlarkFunction) {
        StarlarkCallbackHelper callback =
            new StarlarkCallbackHelper((StarlarkFunction) implicitOutputs, starlarkSemantics);
        builder.setImplicitOutputsFunction(
            new StarlarkImplicitOutputsFunctionWithCallback(callback));
      } else {
        builder.setImplicitOutputsFunction(
            new StarlarkImplicitOutputsFunctionWithMap(
                ImmutableMap.copyOf(
                    Dict.cast(
                        implicitOutputs,
                        String.class,
                        String.class,
                        "implicit outputs of the rule class"))));
      }
    }

    if (outputToGenfiles) {
      builder.setOutputToGenfiles();
    }

    builder.requiresConfigurationFragmentsByStarlarkModuleName(
        Sequence.cast(fragments, String.class, "fragments"));
    builder.setConfiguredTargetFunction(implementation);

    // The rule definition's label and transitive digest typically come from the context of the .bzl
    // file being initialized.
    //
    // Note that if rule() was called via a helper function (a meta-macro), the label and digest of
    // the .bzl file of the innermost stack frame might not be the same as that of the outermost
    // frame. In this case we really do want the outermost, in order to ensure that the digest
    // includes the code that determines the helper function's argument values.
    builder.setRuleDefinitionEnvironmentLabelAndDigest(bzlFile, transitiveDigest);

    builder.addToolchainTypes(parseToolchainTypes(toolchains, labelConverter));

    if (execGroups != Starlark.NONE) {
      Map<String, ExecGroup> execGroupDict =
          Dict.cast(execGroups, String.class, ExecGroup.class, "exec_group");
      for (String group : execGroupDict.keySet()) {
        // TODO(b/151742236): document this in the param documentation.
        if (!StarlarkExecGroupCollection.isValidGroupName(group)) {
          throw Starlark.errorf("Exec group name '%s' is not a valid name.", group);
        }
      }
      builder.addExecGroups(execGroupDict);
    }
    if (test && !builder.hasExecGroup(DEFAULT_TEST_RUNNER_EXEC_GROUP)) {
      builder.addExecGroup(DEFAULT_TEST_RUNNER_EXEC_GROUP);
    }

    if (!buildSetting.equals(Starlark.NONE) && !cfg.equals(Starlark.NONE)) {
      throw Starlark.errorf(
          "Build setting rules cannot use the `cfg` param to apply transitions to themselves.");
    }
    if (!buildSetting.equals(Starlark.NONE)) {
      builder.setBuildSetting((BuildSetting) buildSetting);
    }

    TransitionFactory<RuleTransitionData> transitionFactory = null;
    if (!cfg.equals(Starlark.NONE)) {
      if (cfg instanceof StarlarkDefinedConfigTransition) {
        // defined in Starlark via, cfg = transition
        StarlarkDefinedConfigTransition starlarkDefinedConfigTransition =
            (StarlarkDefinedConfigTransition) cfg;
        transitionFactory = new StarlarkRuleTransitionProvider(starlarkDefinedConfigTransition);
        hasStarlarkDefinedTransition = true;
      } else if (cfg instanceof StarlarkExposedRuleTransitionFactory) {
        // only used for native Android transitions (platforms and feature flags)
        StarlarkExposedRuleTransitionFactory transition =
            (StarlarkExposedRuleTransitionFactory) cfg;
        transition.addToStarlarkRule(ruleDefinitionEnvironment, builder);
        transitionFactory = transition;
      } else {
        throw Starlark.errorf(
            "`cfg` must be set to a transition object initialized by the transition() function.");
      }
    }
    if (parent != null && parent.getTransitionFactory() != null) {
      if (transitionFactory == null) {
        transitionFactory = parent.getTransitionFactory();
      } else {
        transitionFactory =
            ComposingTransitionFactory.of(transitionFactory, parent.getTransitionFactory());
      }
      hasStarlarkDefinedTransition = true;
    }
    if (transitionFactory != null) {
      builder.cfg(transitionFactory);
    }

    boolean hasFunctionTransitionAllowlist = false;
    // Check for existence of the function transition allowlist attribute.
    if (builder.contains(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME)) {
      Attribute attr = builder.getAttribute(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME);
      if (!BuildType.isLabelType(attr.getType())) {
        throw Starlark.errorf("_allowlist_function_transition attribute must be a label type");
      }
      if (attr.getDefaultValueUnchecked() == null) {
        throw Starlark.errorf("_allowlist_function_transition attribute must have a default value");
      }
      Label defaultLabel = (Label) attr.getDefaultValueUnchecked();
      // Check the label value for package and target name, to make sure this works properly
      // in Bazel where it is expected to be found under @bazel_tools.
      if (!(defaultLabel
              .getPackageName()
              .equals(FunctionSplitTransitionAllowlist.LABEL.getPackageName())
          && defaultLabel.getName().equals(FunctionSplitTransitionAllowlist.LABEL.getName()))) {
        throw Starlark.errorf(
            "_allowlist_function_transition attribute (%s) does not have the expected value %s",
            defaultLabel, FunctionSplitTransitionAllowlist.LABEL);
      }
      hasFunctionTransitionAllowlist = true;
    }
    if (hasStarlarkDefinedTransition) {
      if (!bzlFile.getRepository().getName().equals("_builtins")) {
        if (!hasFunctionTransitionAllowlist) {
          // add the allowlist automatically
          builder.add(
              attr(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME, LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .mandatoryBuiltinProviders(ImmutableList.of(PackageSpecificationProvider.class))
                  .value(
                      ruleDefinitionEnvironment.getToolsLabel(
                          FunctionSplitTransitionAllowlist.LABEL_STR)));
        }
        builder.addAllowlistChecker(FUNCTION_TRANSITION_ALLOWLIST_CHECKER);
      }
    } else {
      if (hasFunctionTransitionAllowlist) {
        throw Starlark.errorf(
            "Unused function-based split transition allowlist: %s %s",
            builder.getRuleDefinitionEnvironmentLabel(), builder.getType());
      }
    }

    for (Object o : providesArg) {
      if (!StarlarkAttrModule.isProvider(o)) {
        throw Starlark.errorf(
            "Illegal argument: element in 'provides' is of unexpected type. "
                + "Should be list of providers, but got item of type %s.",
            Starlark.type(o));
      }
    }
    for (StarlarkProviderIdentifier starlarkProvider :
        StarlarkAttrModule.getStarlarkProviderIdentifiers(providesArg)) {
      builder.advertiseStarlarkProvider(starlarkProvider);
    }

    if (!execCompatibleWith.isEmpty()) {
      builder.addExecutionPlatformConstraints(
          parseExecCompatibleWith(execCompatibleWith, labelConverter));
    }

    return new StarlarkRuleFunction(
        builder,
        loc,
        Starlark.toJavaOptional(doc, String.class).map(Starlark::trimDocString));
  }

  private static void checkAttributeName(String name) throws EvalException {
    if (!Identifier.isValid(name)) {
      throw Starlark.errorf("attribute name `%s` is not a valid identifier.", name);
    }
  }

  private static ImmutableList<Pair<String, StarlarkAttrModule.Descriptor>>
      attrObjectToAttributesList(Dict<?, ?> attrs) throws EvalException {
    ImmutableList.Builder<Pair<String, StarlarkAttrModule.Descriptor>> attributes =
        ImmutableList.builder();

    for (Map.Entry<String, Descriptor> attr :
        Dict.cast(attrs, String.class, Descriptor.class, "attrs").entrySet()) {
      Descriptor attrDescriptor = attr.getValue();
      AttributeValueSource source = attrDescriptor.getValueSource();
      checkAttributeName(attr.getKey());
      String attrName = source.convertToNativeName(attr.getKey());
      attributes.add(Pair.of(attrName, attrDescriptor));
    }
    return attributes.build();
  }

  private static ImmutableSet<Label> parseExecCompatibleWith(
      Sequence<?> inputs, LabelConverter labelConverter) throws EvalException {
    ImmutableSet.Builder<Label> parsedLabels = new ImmutableSet.Builder<>();
    for (String input : Sequence.cast(inputs, String.class, "exec_compatible_with")) {
      try {
        Label label = labelConverter.convert(input);
        parsedLabels.add(label);
      } catch (LabelSyntaxException e) {
        throw Starlark.errorf("Unable to parse constraint label '%s': %s", input, e.getMessage());
      }
    }
    return parsedLabels.build();
  }

  @Override
  public StarlarkAspect aspect(
      StarlarkFunction implementation,
      Sequence<?> attributeAspects,
      Dict<?, ?> attrs,
      Sequence<?> requiredProvidersArg,
      Sequence<?> requiredAspectProvidersArg,
      Sequence<?> providesArg,
      Sequence<?> requiredAspects,
      Sequence<?> fragments,
      Sequence<?> hostFragments,
      Sequence<?> toolchains,
      boolean useToolchainTransition,
      Object doc,
      Boolean applyToGeneratingRules,
      Sequence<?> rawExecCompatibleWith,
      Object rawExecGroups,
      Sequence<?> subrulesUnchecked,
      StarlarkThread thread)
      throws EvalException {
    LabelConverter labelConverter = LabelConverter.forBzlEvaluatingThread(thread);

    ImmutableList.Builder<String> attrAspects = ImmutableList.builder();
    for (Object attributeAspect : attributeAspects) {
      String attrName = STRING.convert(attributeAspect, "attr_aspects");

      if (attrName.equals("*") && attributeAspects.size() != 1) {
        throw new EvalException("'*' must be the only string in 'attr_aspects' list");
      }

      if (!attrName.startsWith("_")) {
        attrAspects.add(attrName);
      } else {
        // Implicit attribute names mean either implicit or late-bound attributes
        // (``$attr`` or ``:attr``). Depend on both.
        attrAspects.add(AttributeValueSource.COMPUTED_DEFAULT.convertToNativeName(attrName));
        attrAspects.add(AttributeValueSource.LATE_BOUND.convertToNativeName(attrName));
      }
    }

    ImmutableList<Pair<String, StarlarkAttrModule.Descriptor>> descriptors =
        attrObjectToAttributesList(attrs);

    if (!subrulesUnchecked.isEmpty()) {
      if (!thread.getSemantics().getBool(BuildLanguageOptions.EXPERIMENTAL_RULE_EXTENSION_API)) {
        BuiltinRestriction.failIfCalledOutsideAllowlist(thread, ALLOWLIST_RULE_EXTENSION_API);
      }
    }
    ImmutableList<StarlarkSubrule> subrules =
        Sequence.cast(subrulesUnchecked, StarlarkSubrule.class, "subrules").getImmutableList();
    ImmutableList<Pair<String, Descriptor>> subruleAttributes =
        StarlarkSubrule.discoverAttributes(subrules);
    if (!subruleAttributes.isEmpty()) {
      descriptors =
          ImmutableList.<Pair<String, Descriptor>>builder()
              .addAll(descriptors)
              .addAll(subruleAttributes)
              .build();
    }

    ImmutableList.Builder<Attribute> attributes = ImmutableList.builder();
    ImmutableSet.Builder<String> requiredParams = ImmutableSet.builder();
    for (Pair<String, Descriptor> nameDescriptorPair : descriptors) {
      String nativeName = nameDescriptorPair.first;
      boolean hasDefault = nameDescriptorPair.second.hasDefault();
      Attribute attribute = nameDescriptorPair.second.build(nameDescriptorPair.first);

      if (!Attribute.isImplicit(nativeName) && !Attribute.isLateBound(nativeName)) {
        if (attribute.getType() == Type.STRING) {
          // isValueSet() is always true for attr.string as default value is "" by default.
          hasDefault = !Objects.equals(attribute.getDefaultValue(null), "");
        } else if (attribute.getType() == Type.INTEGER) {
          // isValueSet() is always true for attr.int as default value is 0 by default.
          hasDefault = !Objects.equals(attribute.getDefaultValue(null), StarlarkInt.of(0));
        } else if (attribute.getType() == Type.BOOLEAN) {
          hasDefault = !Objects.equals(attribute.getDefaultValue(null), false);
        } else {
          throw Starlark.errorf(
              "Aspect parameter attribute '%s' must have type 'bool', 'int' or 'string'.",
              nativeName);
        }

        if (hasDefault && attribute.checkAllowedValues()) {
          PredicateWithMessage<Object> allowed = attribute.getAllowedValues();
          Object defaultVal = attribute.getDefaultValue(null);
          if (!allowed.apply(defaultVal)) {
            throw Starlark.errorf(
                "Aspect parameter attribute '%s' has a bad default value: %s",
                nativeName, allowed.getErrorReason(defaultVal));
          }
        }
        if (!hasDefault || attribute.isMandatory()) {
          requiredParams.add(nativeName);
        }
      } else if (!hasDefault) { // Implicit or late bound attribute
        String starlarkName = "_" + nativeName.substring(1);
        if (attribute.isLateBound()
            && !(attribute.getLateBoundDefault() instanceof StarlarkLateBoundDefault)) {
          // Code elsewhere assumes that a late-bound attribute of a Starlark-defined aspects can
          // exist in Java-land only as a StarlarkLateBoundDefault.
          throw Starlark.errorf(
              "Starlark aspect attribute '%s' is late-bound but somehow is not defined in Starlark."
                  + " This violates an invariant inside of Bazel. Please file a bug with"
                  + " instructions for reproducing this. Thanks!",
              starlarkName);
        }
        throw Starlark.errorf("Aspect attribute '%s' has no default value.", starlarkName);
      }
      if (attribute.getDefaultValueUnchecked() instanceof StarlarkComputedDefaultTemplate) {
        // Attributes specifying dependencies using computed value are currently not supported.
        // The limitation is in place because:
        //  - blaze query requires that all possible values are knowable without BuildConguration
        //  - aspects can attach to any rule
        // Current logic in StarlarkComputedDefault is not enough,
        // however {Conservative,Precise}AspectResolver can probably be improved to make that work.
        String starlarkName = "_" + nativeName.substring(1);
        throw Starlark.errorf(
            "Aspect attribute '%s' (%s) with computed default value is unsupported.",
            starlarkName, attribute.getType());
      }
      attributes.add(attribute);
    }

    for (Object o : providesArg) {
      if (!StarlarkAttrModule.isProvider(o)) {
        throw Starlark.errorf(
            "Illegal argument: element in 'provides' is of unexpected type. "
                + "Should be list of providers, but got item of type %s. ",
            Starlark.type(o));
      }
    }

    if (applyToGeneratingRules && !requiredProvidersArg.isEmpty()) {
      throw Starlark.errorf(
          "An aspect cannot simultaneously have required providers and apply to generating rules.");
    }

    ImmutableSet<Label> execCompatibleWith = ImmutableSet.of();
    if (!rawExecCompatibleWith.isEmpty()) {
      execCompatibleWith = parseExecCompatibleWith(rawExecCompatibleWith, labelConverter);
    }

    ImmutableMap<String, ExecGroup> execGroups = ImmutableMap.of();
    if (rawExecGroups != Starlark.NONE) {
      execGroups =
          ImmutableMap.copyOf(
              Dict.cast(rawExecGroups, String.class, ExecGroup.class, "exec_group"));
      for (String group : execGroups.keySet()) {
        // TODO(b/151742236): document this in the param documentation.
        if (!StarlarkExecGroupCollection.isValidGroupName(group)) {
          throw Starlark.errorf("Exec group name '%s' is not a valid name.", group);
        }
      }
    }

    ImmutableSet<ToolchainTypeRequirement> toolchainTypes =
        ImmutableSet.<ToolchainTypeRequirement>builder()
            .addAll(parseToolchainTypes(toolchains, labelConverter))
            .addAll(StarlarkSubrule.discoverToolchains(subrules))
            .build();

    return new StarlarkDefinedAspect(
        implementation,
        Starlark.toJavaOptional(doc, String.class).map(Starlark::trimDocString),
        attrAspects.build(),
        attributes.build(),
        StarlarkAttrModule.buildProviderPredicate(requiredProvidersArg, "required_providers"),
        StarlarkAttrModule.buildProviderPredicate(
            requiredAspectProvidersArg, "required_aspect_providers"),
        StarlarkAttrModule.getStarlarkProviderIdentifiers(providesArg),
        requiredParams.build(),
        ImmutableSet.copyOf(Sequence.cast(requiredAspects, StarlarkAspect.class, "requires")),
        ImmutableSet.copyOf(Sequence.cast(fragments, String.class, "fragments")),
        toolchainTypes,
        applyToGeneratingRules,
        execCompatibleWith,
        execGroups,
        ImmutableSet.copyOf(subrules));
  }

  private static ImmutableSet<String> getLegacyAnyTypeAttrs(RuleClass ruleClass) {
    Attribute attr = ruleClass.getAttributeByNameMaybe("$legacy_any_type_attrs");
    if (attr == null
        || attr.getType() != STRING_LIST
        || !(attr.getDefaultValueUnchecked() instanceof List<?>)) {
      return ImmutableSet.of();
    }
    return ImmutableSet.copyOf(STRING_LIST.cast(attr.getDefaultValueUnchecked()));
  }

  /**
   * The implementation for the magic function "rule" that creates Starlark rule classes.
   *
   * <p>Exactly one of {@link #builder} or {@link #ruleClass} is null except inside {@link #export}.
   */
  public static final class StarlarkRuleFunction implements StarlarkExportable, RuleFunction {
    private RuleClass.Builder builder;

    private RuleClass ruleClass;
    private final Location definitionLocation;
    @Nullable private final String documentation;
    private Label starlarkLabel;

    // TODO(adonovan): merge {Starlark,Builtin}RuleFunction and RuleClass,
    // making the latter a callable, StarlarkExportable value.
    // (Making RuleClasses first-class values will help us to build a
    // rich query output mode that includes values from loaded .bzl files.)
    public StarlarkRuleFunction(
        RuleClass.Builder builder,
        Location definitionLocation,
        Optional<String> documentation) {
      this.builder = builder;
      this.definitionLocation = definitionLocation;
      this.documentation = documentation.orElse(null);
    }

    @Override
    public String getName() {
      return ruleClass != null ? ruleClass.getName() : "unexported rule";
    }

    /**
     * Returns the value of the doc parameter passed to {@code rule()} in Starlark, or an empty
     * Optional if a doc string was not provided.
     */
    public Optional<String> getDocumentation() {
      return Optional.ofNullable(documentation);
    }

    /**
     * Returns the label of the .bzl module where rule() was called, or null if the rule has not
     * been exported yet.
     */
    @Nullable
    public Label getExtensionLabel() {
      return starlarkLabel;
    }

    @Override
    public Object call(StarlarkThread thread, Tuple args, Dict<String, Object> kwargs)
        throws EvalException, InterruptedException {
      if (!args.isEmpty()) {
        throw new EvalException("Unexpected positional arguments");
      }
      try {
        BazelStarlarkContext.checkLoadingPhase(thread, getName());
      } catch (EvalException unused) {
        throw new EvalException(
            "A rule can only be instantiated in a BUILD file, or a macro "
                + "invoked from a BUILD file");
      }
      if (ruleClass == null) {
        throw new EvalException("Invalid rule class hasn't been exported by a bzl file");
      }
      PackageContext pkgContext = thread.getThreadLocal(PackageContext.class);
      if (pkgContext == null) {
        throw new EvalException(
            "Cannot instantiate a rule when loading a .bzl file. "
                + "Rules may be instantiated only in a BUILD thread.");
      }

      validateRulePropagatedAspects(ruleClass);

      ImmutableSet<String> legacyAnyTypeAttrs = getLegacyAnyTypeAttrs(ruleClass);

      // Remove {@link BazelStarlarkContext} to prevent calls to load and analysis time functions.
      // Mutating values in initializers is mostly not a problem, because the attribute values are
      // copied before calling the initializers (<-TODO) and before they are set on the target.
      // Exception is a legacy case allowing arbitrary type of parameter values. In that case the
      // values may be mutated by the initializer, but they are still copied when set on the target.
      BazelStarlarkContext bazelStarlarkContext = BazelStarlarkContext.fromOrFail(thread);
      try {
        thread.setThreadLocal(BazelStarlarkContext.class, null);
        thread.setUncheckedExceptionContext(() -> "an initializer");

        // We call all the initializers of the rule and its ancestor rules, proceeding from child to
        // ancestor, so each initializer can transform the attributes it knows about in turn.
        for (RuleClass currentRuleClass = ruleClass;
            currentRuleClass != null;
            currentRuleClass = currentRuleClass.getStarlarkParent()) {
          if (currentRuleClass.getInitializer() == null) {
            continue;
          }

          // You might feel tempted to inspect the signature of the initializer function. The
          // temptation might come from handling default values, making them work for better for the
          // users.
          // The less magic the better. Do not give in those temptations!
          Dict.Builder<String, Object> initializerKwargs = Dict.builder();
          for (var attr : currentRuleClass.getAttributes()) {
            if (attr.isPublic() && attr.starlarkDefined()) {
              if (kwargs.containsKey(attr.getName())) {
                Object value = kwargs.get(attr.getName());
                if (value == Starlark.NONE) {
                  continue;
                }
                Object reifiedValue =
                    legacyAnyTypeAttrs.contains(attr.getName())
                        ? value
                        : BuildType.copyAndLiftStarlarkValue(
                            currentRuleClass.getName(),
                            attr,
                            value,
                            pkgContext.getBuilder().getLabelConverter());
                initializerKwargs.put(attr.getName(), reifiedValue);
              }
            }
          }
          Object ret =
              Starlark.call(
                  thread,
                  currentRuleClass.getInitializer(),
                  Tuple.of(),
                  initializerKwargs.build(thread.mutability()));
          Dict<String, Object> newKwargs =
              ret == Starlark.NONE
                  ? Dict.empty()
                  : Dict.cast(ret, String.class, Object.class, "rule's initializer return value");

          for (var arg : newKwargs.keySet()) {
            checkAttributeName(arg);
            if (arg.startsWith("_")) {
              // allow setting private attributes from initializers in builtins
              Label definitionLabel = ruleClass.getRuleDefinitionEnvironmentLabel();
              BuiltinRestriction.failIfLabelOutsideAllowlist(
                  definitionLabel,
                  RepositoryMapping.ALWAYS_FALLBACK,
                  ALLOWLIST_RULE_EXTENSION_API_EXPERIMENTAL);
            }
            String nativeName = arg.startsWith("_") ? "$" + arg.substring(1) : arg;
            Attribute attr = currentRuleClass.getAttributeByNameMaybe(nativeName);
            if (attr != null && !attr.starlarkDefined()) {
              throw Starlark.errorf(
                  "Initializer can only set Starlark defined attributes, not '%s'", arg);
            }
            Object value = newKwargs.get(arg);
            Object reifiedValue =
                attr == null
                        || value == Starlark.NONE
                        || legacyAnyTypeAttrs.contains(attr.getName())
                    ? value
                    : BuildType.copyAndLiftStarlarkValue(
                        currentRuleClass.getName(),
                        attr,
                        value,
                        // Reify to the location of the initializer definition
                        currentRuleClass.getLabelConverterForInitializer());
            kwargs.putEntry(nativeName, reifiedValue);
          }
        }
      } finally {
        bazelStarlarkContext.storeInThread(thread);
      }

      BuildLangTypedAttributeValuesMap attributeValues =
          new BuildLangTypedAttributeValuesMap(kwargs);
      try {
        RuleFactory.createAndAddRule(
            pkgContext.getBuilder(),
            ruleClass,
            attributeValues,
            thread
                .getSemantics()
                .getBool(BuildLanguageOptions.INCOMPATIBLE_FAIL_ON_UNKNOWN_ATTRIBUTES),
            pkgContext.getEventHandler(),
            thread.getCallStack());
      } catch (InvalidRuleException | NameConflictException e) {
        throw new EvalException(e);
      }
      return Starlark.NONE;
    }

    private static void validateRulePropagatedAspects(RuleClass ruleClass) throws EvalException {
      for (Attribute attribute : ruleClass.getAttributes()) {
        attribute.validateRulePropagatedAspectsParameters(ruleClass);
      }
    }

    /** Export a RuleFunction from a Starlark file with a given name. */
    @Override
    public void export(EventHandler handler, Label starlarkLabel, String ruleClassName) {
      checkState(ruleClass == null && builder != null);
      this.starlarkLabel = starlarkLabel;
      if (builder.getType() == RuleClassType.TEST != TargetUtils.isTestRuleName(ruleClassName)) {
        errorf(
            handler,
            "Invalid rule class name '%s', test rule class names must end with '_test' and other"
                + " rule classes must not",
            ruleClassName);
        return;
      }

      // lift the subrule attributes to the rule class as if they were declared there, this lets us
      // exploit dependency resolution for "free"
      ImmutableList<Pair<String, Descriptor>> subruleAttributes;
      try {
        var parentSubrules = builder.getParentSubrules();
        ImmutableList<StarlarkSubruleApi> subrulesNotInParents =
            builder.getSubrules().stream()
                .filter(subrule -> !parentSubrules.contains(subrule))
                .collect(toImmutableList());
        subruleAttributes = StarlarkSubrule.discoverAttributes(subrulesNotInParents);
      } catch (EvalException e) {
        errorf(handler, "%s", e.getMessage());
        return;
      }
      for (Pair<String, StarlarkAttrModule.Descriptor> attribute : subruleAttributes) {
        String name = attribute.getFirst();
        StarlarkAttrModule.Descriptor descriptor = attribute.getSecond();

        Attribute attr = descriptor.build(name);

        try {
          builder.addAttribute(attr);
        } catch (IllegalStateException ex) {
          // TODO(bazel-team): stop using unchecked exceptions in this way.
          errorf(handler, "cannot add attribute: %s", ex.getMessage());
        }
      }

      try {
        this.ruleClass = builder.build(ruleClassName, starlarkLabel + "%" + ruleClassName);
      } catch (IllegalArgumentException | IllegalStateException ex) {
        // TODO(adonovan): this catch statement is an abuse of exceptions. Be more specific.
        String msg = ex.getMessage();
        errorf(handler, "%s", msg != null ? msg : ex.toString());
      }

      this.builder = null;
    }

    @FormatMethod
    private void errorf(EventHandler handler, String format, Object... args) {
      handler.handle(Event.error(definitionLocation, String.format(format, args)));
    }

    @Override
    public RuleClass getRuleClass() {
      checkState(ruleClass != null && builder == null);
      return ruleClass;
    }

    @Override
    public boolean isExported() {
      return starlarkLabel != null;
    }

    @Override
    public void repr(Printer printer) {
      if (isExported()) {
        printer.append("<rule ").append(getRuleClass().getName()).append(">");
      } else {
        printer.append("<rule>");
      }
    }

    @Override
    public String toString() {
      return "rule(...)";
    }

    @Override
    public boolean isImmutable() {
      return true;
    }
  }

  @SerializationConstant
  static final AllowlistChecker FUNCTION_TRANSITION_ALLOWLIST_CHECKER =
      AllowlistChecker.builder()
          .setAllowlistAttr(FunctionSplitTransitionAllowlist.NAME)
          .setErrorMessage("Non-allowlisted use of Starlark transition")
          .setLocationCheck(AllowlistChecker.LocationCheck.INSTANCE_OR_DEFINITION)
          .build();

  @SerializationConstant
  static final AllowlistChecker EXTEND_RULE_ALLOWLIST_CHECKER =
      AllowlistChecker.builder()
          .setAllowlistAttr("extend_rule")
          .setErrorMessage("Non-allowlisted attempt to extend a rule.")
          .setLocationCheck(AllowlistChecker.LocationCheck.DEFINITION)
          .build();

  @Override
  public Label label(Object input, StarlarkThread thread) throws EvalException {
    if (input instanceof Label) {
      return (Label) input;
    }
    // The label string is interpreted with respect to the .bzl module containing the call to
    // `Label()`. An alternative to this approach that avoids stack inspection is to have each .bzl
    // module define its own copy of the `Label()` builtin embedding the module's own name. This
    // would lead to peculiarities like foo.bzl being able to call bar.bzl's `Label()` symbol to
    // resolve strings as if it were bar.bzl. It also would prevent sharing the same builtins
    // environment across .bzl files. Hence, we opt for stack inspection.
    BazelModuleContext moduleContext = BazelModuleContext.ofInnermostBzlOrFail(thread, "Label()");
    try {
      return Label.parseWithPackageContext(
          (String) input,
          moduleContext.packageContext(),
          thread.getThreadLocal(Label.RepoMappingRecorder.class));
    } catch (LabelSyntaxException e) {
      throw Starlark.errorf("invalid label in Label(): %s", e.getMessage());
    }
  }

  @Override
  public ExecGroup execGroup(
      Sequence<?> toolchains, Sequence<?> execCompatibleWith, StarlarkThread thread)
      throws EvalException {
    LabelConverter labelConverter = LabelConverter.forBzlEvaluatingThread(thread);
    ImmutableSet<ToolchainTypeRequirement> toolchainTypes =
        parseToolchainTypes(toolchains, labelConverter);
    ImmutableSet<Label> constraints = parseExecCompatibleWith(execCompatibleWith, labelConverter);
    return ExecGroup.builder()
        .toolchainTypes(toolchainTypes)
        .execCompatibleWith(constraints)
        .copyFrom(null)
        .build();
  }

  @Override
  public StarlarkSubruleApi subrule(
      StarlarkFunction implementation,
      Dict<?, ?> attrsUnchecked,
      Sequence<?> toolchainsUnchecked,
      Sequence<?> fragmentsUnchecked,
      Sequence<?> subrulesUnchecked,
      StarlarkThread thread)
      throws EvalException {
    if (!thread.getSemantics().getBool(BuildLanguageOptions.EXPERIMENTAL_RULE_EXTENSION_API)) {
      BuiltinRestriction.failIfCalledOutsideAllowlist(thread, ALLOWLIST_RULE_EXTENSION_API);
    }
    ImmutableMap<String, Descriptor> attrs =
        ImmutableMap.copyOf(Dict.cast(attrsUnchecked, String.class, Descriptor.class, "attrs"));
    ImmutableList<String> fragments =
        Sequence.noneableCast(fragmentsUnchecked, String.class, "fragments").getImmutableList();
    for (Entry<String, Descriptor> attr : attrs.entrySet()) {
      String attrName = attr.getKey();
      Descriptor descriptor = attr.getValue();
      TransitionFactory<AttributeTransitionData> transitionFactory =
          descriptor.getTransitionFactory();
      if (!NoTransition.isInstance(transitionFactory) && !transitionFactory.isTool()) {
        throw Starlark.errorf(
            "bad cfg for attribute '%s': subrules may only have target/exec attributes.", attrName);
      }
      checkAttributeName(attrName);
      Type<?> type = descriptor.getType();
      if (!attrName.startsWith("_")) {
        throw Starlark.errorf(
            "illegal attribute name '%s': subrules may only define private attributes (whose names"
                + " begin with '_').",
            attrName);
      } else if (descriptor.getValueSource() == AttributeValueSource.COMPUTED_DEFAULT) {
        throw Starlark.errorf(
            "illegal default value for attribute '%s': subrules cannot define computed defaults.",
            attrName);
      } else if (!descriptor.hasDefault()) {
        throw Starlark.errorf("for attribute '%s': no default value specified", attrName);
      } else if (type != LABEL && type != LABEL_LIST) {
        throw Starlark.errorf(
            "bad type for attribute '%s': subrule attributes may only be label or lists of labels.",
            attrName);
      }
    }
    ImmutableSet<ToolchainTypeRequirement> toolchains =
        parseToolchainTypes(toolchainsUnchecked, LabelConverter.forBzlEvaluatingThread(thread));
    if (toolchains.size() > 1) {
      throw Starlark.errorf("subrules may require at most 1 toolchain, got: %s", toolchains);
    }
    return new StarlarkSubrule(
        implementation,
        attrs,
        toolchains,
        ImmutableSet.copyOf(fragments),
        ImmutableSet.copyOf(Sequence.cast(subrulesUnchecked, StarlarkSubrule.class, "subrules")));
  }

  private static ImmutableSet<ToolchainTypeRequirement> parseToolchainTypes(
      Sequence<?> rawToolchains, LabelConverter labelConverter) throws EvalException {
    Map<Label, ToolchainTypeRequirement> toolchainTypes = new HashMap<>();

    for (Object rawToolchain : rawToolchains) {
      ToolchainTypeRequirement toolchainType = parseToolchainType(rawToolchain, labelConverter);
      Label typeLabel = toolchainType.toolchainType();
      ToolchainTypeRequirement previous = toolchainTypes.get(typeLabel);
      if (previous != null) {
        // Keep the one with the strictest requirements.
        toolchainType = ToolchainTypeRequirement.strictest(previous, toolchainType);
      }
      toolchainTypes.put(typeLabel, toolchainType);
    }

    return ImmutableSet.copyOf(toolchainTypes.values());
  }

  private static ToolchainTypeRequirement parseToolchainType(
      Object rawToolchain, LabelConverter labelConverter) throws EvalException {
    // Handle actual ToolchainTypeRequirement objects.
    if (rawToolchain instanceof ToolchainTypeRequirement) {
      return (ToolchainTypeRequirement) rawToolchain;
    }

    // Handle Label-like objects.
    Label toolchainLabel = null;
    if (rawToolchain instanceof Label) {
      toolchainLabel = (Label) rawToolchain;
    } else if (rawToolchain instanceof String) {
      try {
        toolchainLabel = labelConverter.convert((String) rawToolchain);
      } catch (LabelSyntaxException e) {
        throw Starlark.errorf(
            "Unable to parse toolchain_type label '%s': %s", rawToolchain, e.getMessage());
      }
    }

    if (toolchainLabel != null) {
      return ToolchainTypeRequirement.builder(toolchainLabel).mandatory(true).build();
    }

    // It's not a valid type.
    throw Starlark.errorf(
        "'toolchains' takes a toolchain_type, Label, or String, but instead got a %s",
        rawToolchain.getClass().getSimpleName());
  }
}
