fix(uv): fix UV_BIN usage with current_toolchain (#2074)

Before this PR the `uv` toolchain could not be used in a `genrule` it
seems because the `//python/uv:toolchain` does not have the necessary
providers for using the make variables and the re-exporting of the make
variables from the `toolchain` in the `current_toolchain` rule did not
seem to work.

This PR removes the provider construction in the `toolchain` and does
that only in the `current_toolchain`. This better mirrors how the Python
toolchains are setup (grepping `PYTHON3` is sufficient to get examples).
This also splits out work done in #2059 to decrease its scope, so that
this can be discussed separately.

Work towards #1975
diff --git a/.bazelrc b/.bazelrc
index 0833d8d..1ca469c 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -4,8 +4,8 @@
 # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
 # To update these lines, execute
 # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
-build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered
-query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered
+build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered
+query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered
 
 test --test_output=errors
 
diff --git a/MODULE.bazel b/MODULE.bazel
index b6d198f..2e0d06d 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -130,3 +130,17 @@
     "build_bazel_bazel_rolling",
     "build_bazel_bazel_self",
 )
+
+# EXPERIMENTAL: This is experimental and may be removed without notice
+uv = use_extension(
+    "//python/uv:extensions.bzl",
+    "uv",
+    dev_dependency = True,
+)
+uv.toolchain(uv_version = "0.2.23")
+use_repo(uv, "uv_toolchains")
+
+register_toolchains(
+    "@uv_toolchains//:all",
+    dev_dependency = True,
+)
diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel
index 3961c90..383bdfc 100644
--- a/python/uv/BUILD.bazel
+++ b/python/uv/BUILD.bazel
@@ -41,7 +41,10 @@
     # even if no toolchain is registered.
     tags = ["manual"],
     # EXPERIMENTAL: Visibility is restricted to allow for changes.
-    visibility = ["@rules_python//examples:__subpackages__"],
+    visibility = [
+        "//:__subpackages__",
+        "@rules_python//examples:__subpackages__",
+    ],
 )
 
 bzl_library(
diff --git a/python/uv/private/current_toolchain.bzl b/python/uv/private/current_toolchain.bzl
index cd4a592..91a25cb 100644
--- a/python/uv/private/current_toolchain.bzl
+++ b/python/uv/private/current_toolchain.bzl
@@ -30,7 +30,9 @@
     # Bazel requires executable rules to create the executable themselves,
     # so we create a symlink in this rule so that it appears this rule created its executable.
     original_uv_executable = toolchain_info.uv_toolchain_info.uv[DefaultInfo].files_to_run.executable
-    symlink_uv_executable = ctx.actions.declare_file("uv_symlink_{}".format(original_uv_executable.basename))
+
+    # Use `uv` as the name of the binary to make the help message well formatted
+    symlink_uv_executable = ctx.actions.declare_file("current_toolchain/uv".format(original_uv_executable.basename))
     ctx.actions.symlink(output = symlink_uv_executable, target_file = original_uv_executable)
 
     new_default_info = DefaultInfo(
@@ -39,10 +41,14 @@
         executable = symlink_uv_executable,
     )
 
+    template_variable_info = platform_common.TemplateVariableInfo({
+        "UV_BIN": symlink_uv_executable.path,
+    })
+
     return [
         toolchain_info,
         new_default_info,
-        toolchain_info.template_variable_info,
+        template_variable_info,
         toolchain_info.uv_toolchain_info,
     ]
 
diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl
index dbfda0b..3cd5850 100644
--- a/python/uv/toolchain.bzl
+++ b/python/uv/toolchain.bzl
@@ -31,21 +31,16 @@
         uv = uv,
         version = ctx.attr.version,
     )
-    template_variable_info = platform_common.TemplateVariableInfo({
-        "UV_BIN": uv[DefaultInfo].files_to_run.executable.path,
-    })
 
     # Export all the providers inside our ToolchainInfo
     # so the current_toolchain rule can grab and re-export them.
     toolchain_info = platform_common.ToolchainInfo(
         default_info = default_info,
-        template_variable_info = template_variable_info,
         uv_toolchain_info = uv_toolchain_info,
     )
     return [
         default_info,
         toolchain_info,
-        template_variable_info,
     ]
 
 uv_toolchain = rule(
diff --git a/tests/uv/toolchain/BUILD.bazel b/tests/uv/toolchain/BUILD.bazel
new file mode 100644
index 0000000..137b4e0
--- /dev/null
+++ b/tests/uv/toolchain/BUILD.bazel
@@ -0,0 +1,22 @@
+load("//python:py_test.bzl", "py_test")
+load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")  # buildifier: disable=bzl-visibility
+
+# We only test this feature when `bzlmod` is enabled.
+_TARGET_COMPATIBLE_WITH = [] if BZLMOD_ENABLED else ["@platforms//:incompatible"]
+
+genrule(
+    name = "uv_help",
+    outs = ["uv_help.txt"],
+    cmd = "$(UV_BIN) --python-fetch manual --help >$@",
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+    toolchains = ["//python/uv:current_toolchain"],
+)
+
+py_test(
+    name = "uv_help_test",
+    srcs = ["uv_help_test.py"],
+    data = [":uv_help"],
+    env = {"DATA": "$(rlocationpath :uv_help)"},
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+    deps = ["//python/runfiles"],
+)
diff --git a/tests/uv/toolchain/uv_help_test.py b/tests/uv/toolchain/uv_help_test.py
new file mode 100755
index 0000000..be5e755
--- /dev/null
+++ b/tests/uv/toolchain/uv_help_test.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import os
+import unittest
+from pathlib import Path
+
+from python.runfiles import runfiles
+
+
+class TestUV(unittest.TestCase):
+    def test_uv_help(self):
+        rfiles = runfiles.Create()
+        assert rfiles is not None, "rfiles creation failed"
+
+        data_rpath = os.environ["DATA"]
+        uv_help_path = rfiles.Rlocation(data_rpath)
+        assert (
+            uv_help_path is not None
+        ), f"the rlocation path was not found: {data_rpath}"
+
+        uv_help = Path(uv_help_path).read_text()
+
+        self.assertIn("Usage: uv [OPTIONS] <COMMAND>", uv_help)
+
+
+if __name__ == "__main__":
+    unittest.main()