refactor: remove most of semantics (#3475)

This removes the majority of the "semantics" plugin objects. These are a
holdover
from making the code more amenable towards being extended by the Google
implementation.

py_library semantics are completely removed. Most of py_binary has had
semantics
removed. I've left the debugger, build data, and cc deps hooks in for
now, since
that functionality can still be folded into the code.
diff --git a/python/private/common.bzl b/python/private/common.bzl
index ddeea6e..19f2f39 100644
--- a/python/private/common.bzl
+++ b/python/private/common.bzl
@@ -43,22 +43,10 @@
 
 def create_binary_semantics_struct(
         *,
-        create_executable,
-        get_cc_details_for_binary,
         get_central_uncachable_version_file,
-        get_coverage_deps,
         get_debugger_deps,
-        get_extra_common_runfiles_for_binary,
-        get_extra_providers,
-        get_extra_write_build_data_env,
-        get_interpreter_path,
-        get_imports,
         get_native_deps_dso_name,
-        get_native_deps_user_link_flags,
-        get_stamp_flag,
-        maybe_precompile,
         should_build_native_deps_dso,
-        should_create_init_files,
         should_include_build_data):
     """Helper to ensure a semantics struct has all necessary fields.
 
@@ -66,42 +54,15 @@
     the necessary functions are being correctly provided.
 
     Args:
-        create_executable: Callable; creates a binary's executable output. See
-            py_executable.bzl#py_executable_base_impl for details.
-        get_cc_details_for_binary: Callable that returns a `CcDetails` struct; see
-            `create_cc_detail_struct`.
         get_central_uncachable_version_file: Callable that returns an optional
             Artifact; this artifact is special: it is never cached and is a copy
             of `ctx.version_file`; see py_builtins.copy_without_caching
-        get_coverage_deps: Callable that returns a list of Targets for making
-            coverage work; only called if coverage is enabled.
         get_debugger_deps: Callable that returns a list of Targets that provide
             custom debugger support; only called for target-configuration.
-        get_extra_common_runfiles_for_binary: Callable that returns a runfiles
-            object of extra runfiles a binary should include.
-        get_extra_providers: Callable that returns extra providers; see
-            py_executable.bzl#_create_providers for details.
-        get_extra_write_build_data_env: Callable that returns a dict[str, str]
-            of additional environment variable to pass to build data generation.
-        get_interpreter_path: Callable that returns an optional string, which is
-            the path to the Python interpreter to use for running the binary.
-        get_imports: Callable that returns a list of the target's import
-            paths (from the `imports` attribute, so just the target's own import
-            path strings, not from dependencies).
         get_native_deps_dso_name: Callable that returns a string, which is the
             basename (with extension) of the native deps DSO library.
-        get_native_deps_user_link_flags: Callable that returns a list of strings,
-            which are any extra linker flags to pass onto the native deps DSO
-            linking action.
-        get_stamp_flag: Callable that returns bool of if the --stamp flag was
-            enabled or not.
-        maybe_precompile: Callable that may optional precompile the input `.py`
-            sources and returns the full set of desired outputs derived from
-            the source files (e.g., both py and pyc, only one of them, etc).
         should_build_native_deps_dso: Callable that returns bool; True if
             building a native deps DSO is supported, False if not.
-        should_create_init_files: Callable that returns bool; True if
-            `__init__.py` files should be generated, False if not.
         should_include_build_data: Callable that returns bool; True if
             build data should be generated, False if not.
     Returns:
@@ -109,50 +70,13 @@
     """
     return struct(
         # keep-sorted
-        create_executable = create_executable,
-        get_cc_details_for_binary = get_cc_details_for_binary,
         get_central_uncachable_version_file = get_central_uncachable_version_file,
-        get_coverage_deps = get_coverage_deps,
         get_debugger_deps = get_debugger_deps,
-        get_extra_common_runfiles_for_binary = get_extra_common_runfiles_for_binary,
-        get_extra_providers = get_extra_providers,
-        get_extra_write_build_data_env = get_extra_write_build_data_env,
-        get_imports = get_imports,
-        get_interpreter_path = get_interpreter_path,
         get_native_deps_dso_name = get_native_deps_dso_name,
-        get_native_deps_user_link_flags = get_native_deps_user_link_flags,
-        get_stamp_flag = get_stamp_flag,
-        maybe_precompile = maybe_precompile,
         should_build_native_deps_dso = should_build_native_deps_dso,
-        should_create_init_files = should_create_init_files,
         should_include_build_data = should_include_build_data,
     )
 
-def create_library_semantics_struct(
-        *,
-        get_cc_info_for_library,
-        get_imports,
-        maybe_precompile):
-    """Create a `LibrarySemantics` struct.
-
-    Call this instead of a raw call to `struct(...)`; it'll help ensure all
-    the necessary functions are being correctly provided.
-
-    Args:
-        get_cc_info_for_library: Callable that returns a CcInfo for the library;
-            see py_library_impl for arg details.
-        get_imports: Callable; see create_binary_semantics_struct.
-        maybe_precompile: Callable; see create_binary_semantics_struct.
-    Returns:
-        a `LibrarySemantics` struct.
-    """
-    return struct(
-        # keep sorted
-        get_cc_info_for_library = get_cc_info_for_library,
-        get_imports = get_imports,
-        maybe_precompile = maybe_precompile,
-    )
-
 def create_cc_details_struct(
         *,
         cc_info_for_propagating,
@@ -255,12 +179,11 @@
 
     return cc_common.merge_cc_infos(cc_infos = cc_infos)
 
-def collect_imports(ctx, semantics):
+def collect_imports(ctx):
     """Collect the direct and transitive `imports` strings.
 
     Args:
         ctx: {type}`ctx` the current target ctx
-        semantics: semantics object for fetching direct imports.
 
     Returns:
         {type}`depset[str]` of import paths
@@ -271,13 +194,11 @@
             transitive.append(dep[PyInfo].imports)
         if BuiltinPyInfo != None and BuiltinPyInfo in dep:
             transitive.append(dep[BuiltinPyInfo].imports)
-    return depset(direct = semantics.get_imports(ctx), transitive = transitive)
+    return depset(direct = get_imports(ctx), transitive = transitive)
 
 def get_imports(ctx):
     """Gets the imports from a rule's `imports` attribute.
 
-    See create_binary_semantics_struct for details about this function.
-
     Args:
         ctx: Rule ctx.
 
diff --git a/python/private/py_executable.bzl b/python/private/py_executable.bzl
index 9084454..2e167b9 100644
--- a/python/private/py_executable.bzl
+++ b/python/private/py_executable.bzl
@@ -47,7 +47,6 @@
     "create_py_info",
     "csv",
     "filter_to_py_srcs",
-    "get_imports",
     "is_bool",
     "relative_path",
     "runfiles_root_path",
@@ -267,42 +266,18 @@
 def create_binary_semantics():
     return create_binary_semantics_struct(
         # keep-sorted start
-        create_executable = _create_executable,
-        get_cc_details_for_binary = _get_cc_details_for_binary,
         get_central_uncachable_version_file = lambda ctx: None,
-        get_coverage_deps = _get_coverage_deps,
         get_debugger_deps = _get_debugger_deps,
-        get_extra_common_runfiles_for_binary = lambda ctx: ctx.runfiles(),
-        get_extra_providers = _get_extra_providers,
-        get_extra_write_build_data_env = lambda ctx: {},
-        get_imports = get_imports,
-        get_interpreter_path = _get_interpreter_path,
         get_native_deps_dso_name = _get_native_deps_dso_name,
-        get_native_deps_user_link_flags = _get_native_deps_user_link_flags,
-        get_stamp_flag = _get_stamp_flag,
-        maybe_precompile = maybe_precompile,
         should_build_native_deps_dso = lambda ctx: False,
-        should_create_init_files = _should_create_init_files,
         should_include_build_data = lambda ctx: False,
         # keep-sorted end
     )
 
-def _get_coverage_deps(ctx, runtime_details):
-    _ = ctx, runtime_details  # @unused
-    return []
-
 def _get_debugger_deps(ctx, runtime_details):
     _ = ctx, runtime_details  # @unused
     return []
 
-def _get_extra_providers(ctx, main_py, runtime_details):
-    _ = ctx, main_py, runtime_details  # @unused
-    return []
-
-def _get_stamp_flag(ctx):
-    # NOTE: Undocumented API; private to builtins
-    return ctx.configuration.stamp_binaries
-
 def _should_create_init_files(ctx):
     if ctx.attr.legacy_create_init == -1:
         return not read_possibly_native_flag(ctx, "default_to_explicit_init_py")
@@ -994,10 +969,6 @@
     _ = ctx  # @unused
     fail("Building native deps DSO not supported.")
 
-def _get_native_deps_user_link_flags(ctx):
-    _ = ctx  # @unused
-    fail("Building native deps DSO not supported.")
-
 def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment = []):
     """Base rule implementation for a Python executable.
 
@@ -1022,7 +993,7 @@
     else:
         main_py = None
     direct_sources = filter_to_py_srcs(ctx.files.srcs)
-    precompile_result = semantics.maybe_precompile(ctx, direct_sources)
+    precompile_result = maybe_precompile(ctx, direct_sources)
 
     required_py_files = precompile_result.keep_srcs
     required_pyc_files = []
@@ -1046,20 +1017,17 @@
     default_outputs.add(precompile_result.keep_srcs)
     default_outputs.add(required_pyc_files)
 
-    imports = collect_imports(ctx, semantics)
+    imports = collect_imports(ctx)
 
-    runtime_details = _get_runtime_details(ctx, semantics)
-    if ctx.configuration.coverage_enabled:
-        extra_deps = semantics.get_coverage_deps(ctx, runtime_details)
-    else:
-        extra_deps = []
+    runtime_details = _get_runtime_details(ctx)
+    extra_deps = []
 
     # The debugger dependency should be prevented by select() config elsewhere,
     # but just to be safe, also guard against adding it to the output here.
     if not _is_tool_config(ctx):
         extra_deps.extend(semantics.get_debugger_deps(ctx, runtime_details))
 
-    cc_details = semantics.get_cc_details_for_binary(ctx, extra_deps = extra_deps)
+    cc_details = _get_cc_details_for_binary(ctx, extra_deps = extra_deps)
     native_deps_details = _get_native_deps_details(
         ctx,
         semantics = semantics,
@@ -1078,11 +1046,10 @@
             runtime_details.runfiles,
             cc_details.extra_runfiles,
             native_deps_details.runfiles,
-            semantics.get_extra_common_runfiles_for_binary(ctx),
         ],
         semantics = semantics,
     )
-    exec_result = semantics.create_executable(
+    exec_result = _create_executable(
         ctx,
         executable = executable,
         main_py = main_py,
@@ -1122,7 +1089,6 @@
         runtime_details = runtime_details,
         cc_info = cc_details.cc_info_for_propagating,
         inherited_environment = inherited_environment,
-        semantics = semantics,
         output_groups = exec_result.output_groups,
     )
 
@@ -1154,7 +1120,7 @@
 
     return executable
 
-def _get_runtime_details(ctx, semantics):
+def _get_runtime_details(ctx):
     """Gets various information about the Python runtime to use.
 
     While most information comes from the toolchain, various legacy and
@@ -1162,7 +1128,6 @@
 
     Args:
         ctx: Rule ctx
-        semantics: A `BinarySemantics` struct; see `create_binary_semantics_struct`
 
     Returns:
         A struct; see inline-field comments of the return value for details.
@@ -1203,7 +1168,7 @@
     else:
         runtime_files = depset()
 
-    executable_interpreter_path = semantics.get_interpreter_path(
+    executable_interpreter_path = _get_interpreter_path(
         ctx,
         runtime = effective_runtime,
         flag_interpreter_path = flag_interpreter_path,
@@ -1336,7 +1301,7 @@
 
     common_runfiles = common_runfiles.build(ctx)
 
-    if semantics.should_create_init_files(ctx):
+    if _should_create_init_files(ctx):
         common_runfiles = _py_builtins.merge_runfiles_with_generated_inits_empty_files_supplier(
             ctx = ctx,
             runfiles = common_runfiles,
@@ -1352,11 +1317,10 @@
     # removed and another way found to locate the underlying build data file.
     data_runfiles = runfiles_with_exe
 
-    if is_stamping_enabled(ctx, semantics) and semantics.should_include_build_data(ctx):
+    if is_stamping_enabled(ctx) and semantics.should_include_build_data(ctx):
         build_data_file, build_data_runfiles = _create_runfiles_with_build_data(
             ctx,
             semantics.get_central_uncachable_version_file(ctx),
-            semantics.get_extra_write_build_data_env(ctx),
         )
         default_runfiles = runfiles_with_exe.merge(build_data_runfiles)
     else:
@@ -1372,19 +1336,17 @@
 
 def _create_runfiles_with_build_data(
         ctx,
-        central_uncachable_version_file,
-        extra_write_build_data_env):
+        central_uncachable_version_file):
     build_data_file = _write_build_data(
         ctx,
         central_uncachable_version_file,
-        extra_write_build_data_env,
     )
     build_data_runfiles = ctx.runfiles(files = [
         build_data_file,
     ])
     return build_data_file, build_data_runfiles
 
-def _write_build_data(ctx, central_uncachable_version_file, extra_write_build_data_env):
+def _write_build_data(ctx, central_uncachable_version_file):
     # TODO: Remove this logic when a central file is always available
     if not central_uncachable_version_file:
         version_file = ctx.actions.declare_file(ctx.label.name + "-uncachable_version_file.txt")
@@ -1430,7 +1392,7 @@
 
     ctx.actions.run(
         executable = ctx.executable._build_data_gen,
-        env = dicts.add({
+        env = {
             # NOTE: ctx.info_file is undocumented; see
             # https://github.com/bazelbuild/bazel/issues/9363
             "INFO_FILE": ctx.info_file.path,
@@ -1438,7 +1400,7 @@
             "PLATFORM": cc_helper.find_cpp_toolchain(ctx).toolchain_id,
             "TARGET": str(ctx.label),
             "VERSION_FILE": version_file.path,
-        }, extra_write_build_data_env),
+        },
         inputs = depset(
             direct = direct_inputs,
         ),
@@ -1489,12 +1451,9 @@
         feature_configuration = cc_feature_config.feature_configuration,
         cc_toolchain = cc_details.cc_toolchain,
         test_only_target = is_test,  # private
-        stamp = 1 if is_stamping_enabled(ctx, semantics) else 0,
+        stamp = 1 if is_stamping_enabled(ctx) else 0,
         main_output = linked_lib,  # private
         use_shareable_artifact_factory = True,  # private
-        # NOTE: Only flags not captured by cc_info.linking_context need to
-        # be manually passed
-        user_link_flags = semantics.get_native_deps_user_link_flags(ctx),
     )
     return struct(
         dso = dso,
@@ -1634,12 +1593,11 @@
     # "ab/c.py".endswith("b/c.py") from incorrectly matching.
     return ("/" + path).endswith("/" + endswith)
 
-def is_stamping_enabled(ctx, semantics):
+def is_stamping_enabled(ctx):
     """Tells if stamping is enabled or not.
 
     Args:
         ctx: The rule ctx
-        semantics: a semantics struct (see create_semantics_struct).
     Returns:
         bool; True if stamping is enabled, False if not.
     """
@@ -1652,7 +1610,8 @@
     elif stamp == 0:
         return False
     elif stamp == -1:
-        return semantics.get_stamp_flag(ctx)
+        # NOTE: Undocumented API; private to builtins
+        return ctx.configuration.stamp_binaries
     else:
         fail("Unsupported `stamp` value: {}".format(stamp))
 
@@ -1678,8 +1637,7 @@
         cc_info,
         inherited_environment,
         runtime_details,
-        output_groups,
-        semantics):
+        output_groups):
     """Creates the providers an executable should return.
 
     Args:
@@ -1708,7 +1666,6 @@
             is run within.
         runtime_details: struct of runtime information; see _get_runtime_details()
         output_groups: dict[str, depset[File]]; used to create OutputGroupInfo
-        semantics: BinarySemantics struct; see create_binary_semantics()
 
     Returns:
         A list of modern providers.
@@ -1783,13 +1740,6 @@
     if builtin_py_info:
         providers.append(builtin_py_info)
     providers.append(create_output_group_info(py_info.transitive_sources, output_groups))
-
-    extra_providers = semantics.get_extra_providers(
-        ctx,
-        main_py = main_py,
-        runtime_details = runtime_details,
-    )
-    providers.extend(extra_providers)
     return providers
 
 def _create_run_environment_info(ctx, inherited_environment):
diff --git a/python/private/py_library.bzl b/python/private/py_library.bzl
index 6edb25a..de73a53 100644
--- a/python/private/py_library.bzl
+++ b/python/private/py_library.bzl
@@ -32,11 +32,9 @@
     "collect_imports",
     "collect_runfiles",
     "create_instrumented_files_info",
-    "create_library_semantics_struct",
     "create_output_group_info",
     "create_py_info",
     "filter_to_py_srcs",
-    "get_imports",
 )
 load(":common_labels.bzl", "labels")
 load(":flags.bzl", "AddSrcsToRunfilesFlag", "PrecompileFlag", "VenvsSitePackages")
@@ -121,29 +119,18 @@
     },
 )
 
-def _py_library_impl_with_semantics(ctx):
-    return py_library_impl(
-        ctx,
-        semantics = create_library_semantics_struct(
-            get_imports = get_imports,
-            maybe_precompile = maybe_precompile,
-            get_cc_info_for_library = collect_cc_info,
-        ),
-    )
-
-def py_library_impl(ctx, *, semantics):
+def py_library_impl(ctx):
     """Abstract implementation of py_library rule.
 
     Args:
         ctx: The rule ctx
-        semantics: A `LibrarySemantics` struct; see `create_library_semantics_struct`
 
     Returns:
         A list of modern providers to propagate.
     """
     direct_sources = filter_to_py_srcs(ctx.files.srcs)
 
-    precompile_result = semantics.maybe_precompile(ctx, direct_sources)
+    precompile_result = maybe_precompile(ctx, direct_sources)
 
     required_py_files = precompile_result.keep_srcs
     required_pyc_files = []
@@ -172,9 +159,9 @@
     imports = []
     venv_symlinks = []
 
-    imports, venv_symlinks = _get_imports_and_venv_symlinks(ctx, semantics)
+    imports, venv_symlinks = _get_imports_and_venv_symlinks(ctx)
 
-    cc_info = semantics.get_cc_info_for_library(ctx)
+    cc_info = collect_cc_info(ctx)
     py_info, builtins_py_info = create_py_info(
         ctx,
         original_sources = direct_sources,
@@ -243,7 +230,7 @@
         version.normalize(version_str),  # will have no dashes either
     )
 
-def _get_imports_and_venv_symlinks(ctx, semantics):
+def _get_imports_and_venv_symlinks(ctx):
     imports = depset()
     venv_symlinks = []
     if VenvsSitePackages.is_enabled(ctx):
@@ -268,7 +255,7 @@
             namespace_package_files = ctx.files.namespace_package_files,
         )
     else:
-        imports = collect_imports(ctx, semantics)
+        imports = collect_imports(ctx)
     return imports, venv_symlinks
 
 _MaybeBuiltinPyInfo = [BuiltinPyInfo] if BuiltinPyInfo != None else []
@@ -288,7 +275,7 @@
         for creating a `py_library` rule.
     """
     builder = ruleb.Rule(
-        implementation = _py_library_impl_with_semantics,
+        implementation = py_library_impl,
         doc = _DEFAULT_PY_LIBRARY_DOC,
         exec_groups = dict(REQUIRED_EXEC_GROUP_BUILDERS),
         attrs = LIBRARY_ATTRS,