Added TemplateVariableInfo to rust_toolchain (#1377)

diff --git a/rust/private/toolchain_utils.bzl b/rust/private/toolchain_utils.bzl
index fcd4fb7..4e32b6d 100644
--- a/rust/private/toolchain_utils.bzl
+++ b/rust/private/toolchain_utils.bzl
@@ -80,3 +80,28 @@
     ],
     incompatible_use_toolchain_transition = True,
 )
+
+def _current_rust_toolchain_impl(ctx):
+    toolchain = ctx.toolchains[str(Label("@rules_rust//rust:toolchain"))]
+
+    return [
+        toolchain,
+        toolchain.make_variables,
+        DefaultInfo(
+            files = depset([
+                toolchain.rustc,
+                toolchain.rust_doc,
+                toolchain.rustfmt,
+                toolchain.cargo,
+            ]),
+        ),
+    ]
+
+current_rust_toolchain = rule(
+    doc = "A rule for exposing the current registered `rust_toolchain`.",
+    implementation = _current_rust_toolchain_impl,
+    toolchains = [
+        str(Label("@rules_rust//rust:toolchain")),
+    ],
+    incompatible_use_toolchain_transition = True,
+)
diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl
index 0ad8de9..b3e8e80 100644
--- a/rust/private/utils.bzl
+++ b/rust/private/utils.bzl
@@ -186,12 +186,12 @@
         )
 
 def _expand_location(ctx, env, data):
-    """A trivial helper for `_expand_locations`
+    """A trivial helper for `expand_dict_value_locations` and `expand_list_element_locations`
 
     Args:
         ctx (ctx): The rule's context object
         env (str): The value possibly containing location macros to expand.
-        data (sequence of Targets): see `_expand_locations`
+        data (sequence of Targets): See one of the parent functions.
 
     Returns:
         string: The location-macro expanded version of the string.
@@ -199,8 +199,12 @@
     for directive in ("$(execpath ", "$(location "):
         if directive in env:
             # build script runner will expand pwd to execroot for us
-            env = env.replace(directive, "${pwd}/" + directive)
-    return ctx.expand_location(env, data)
+            env = env.replace(directive, "$${pwd}/" + directive)
+    return ctx.expand_make_variables(
+        env,
+        ctx.expand_location(env, data),
+        {},
+    )
 
 def expand_dict_value_locations(ctx, env, data):
     """Performs location-macro expansion on string values.
@@ -217,7 +221,9 @@
     as compilation happens in a separate sandbox folder, so when it comes time
     to read the file at runtime, the path is no longer valid.
 
-    See [`expand_location`](https://docs.bazel.build/versions/main/skylark/lib/ctx.html#expand_location) for detailed documentation.
+    For detailed documentation, see:
+    - [`expand_location`](https://bazel.build/rules/lib/ctx#expand_location)
+    - [`expand_make_variables`](https://bazel.build/rules/lib/ctx#expand_make_variables)
 
     Args:
         ctx (ctx): The rule's context object
@@ -238,7 +244,9 @@
     which process_wrapper and build_script_runner will expand at run time
     to the absolute path.
 
-    See [`expand_location`](https://docs.bazel.build/versions/main/skylark/lib/ctx.html#expand_location) for detailed documentation.
+    For detailed documentation, see:
+    - [`expand_location`](https://bazel.build/rules/lib/ctx#expand_location)
+    - [`expand_make_variables`](https://bazel.build/rules/lib/ctx#expand_make_variables)
 
     Args:
         ctx (ctx): The rule's context object
diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl
index 7d60256..90dea6e 100644
--- a/rust/toolchain.bzl
+++ b/rust/toolchain.bzl
@@ -465,6 +465,24 @@
     sysroot_path = sysroot.sysroot_anchor.dirname
     sysroot_short_path, _, _ = sysroot.sysroot_anchor.short_path.rpartition("/")
 
+    # Variables for make variable expansion
+    make_variables = {
+        "RUSTC": sysroot.rustc.path,
+        "RUSTDOC": sysroot.rustdoc.path,
+        "RUST_DEFAULT_EDITION": ctx.attr.default_edition or "",
+        "RUST_SYSROOT": sysroot_path,
+    }
+
+    if sysroot.cargo:
+        make_variables.update({
+            "CARGO": sysroot.cargo.path,
+        })
+
+    if sysroot.rustfmt:
+        make_variables.update({
+            "RUSTFMT": sysroot.rustfmt.path,
+        })
+
     toolchain = platform_common.ToolchainInfo(
         all_files = sysroot.all_files,
         binary_ext = ctx.attr.binary_ext,
@@ -477,6 +495,7 @@
         env = ctx.attr.env,
         exec_triple = ctx.attr.exec_triple,
         libstd_and_allocator_ccinfo = _make_libstd_and_allocator_ccinfo(ctx, rust_std, ctx.attr.allocator_library),
+        make_variables = platform_common.TemplateVariableInfo(make_variables),
         os = ctx.attr.os,
         rust_doc = sysroot.rustdoc,
         rust_lib = sysroot.rust_std,  # `rust_lib` is deprecated and only exists for legacy support.
diff --git a/rust/toolchain/BUILD.bazel b/rust/toolchain/BUILD.bazel
index 3b7ad50..dffc380 100644
--- a/rust/toolchain/BUILD.bazel
+++ b/rust/toolchain/BUILD.bazel
@@ -1,4 +1,4 @@
-load("//rust/private:toolchain_utils.bzl", "toolchain_files")
+load("//rust/private:toolchain_utils.bzl", "current_rust_toolchain", "toolchain_files")
 
 package(default_visibility = ["//visibility:public"])
 
@@ -90,6 +90,10 @@
     deprecation = "instead use `@rules_rust//rust/toolchain:current_rust_stdlib_files`",
 )
 
+current_rust_toolchain(
+    name = "current_rust_toolchain",
+)
+
 filegroup(
     name = "distro",
     srcs = [
diff --git a/test/unit/toolchain_make_variables/BUILD.bazel b/test/unit/toolchain_make_variables/BUILD.bazel
new file mode 100644
index 0000000..2534bd8
--- /dev/null
+++ b/test/unit/toolchain_make_variables/BUILD.bazel
@@ -0,0 +1,5 @@
+load(":toolchain_make_variables_test.bzl", "toolchain_make_variable_test_suite")
+
+toolchain_make_variable_test_suite(
+    name = "toolchain_make_variable_test_suite",
+)
diff --git a/test/unit/toolchain_make_variables/main.rs b/test/unit/toolchain_make_variables/main.rs
new file mode 100644
index 0000000..da0f5d9
--- /dev/null
+++ b/test/unit/toolchain_make_variables/main.rs
@@ -0,0 +1 @@
+pub fn main() {}
diff --git a/test/unit/toolchain_make_variables/toolchain_make_variables_test.bzl b/test/unit/toolchain_make_variables/toolchain_make_variables_test.bzl
new file mode 100644
index 0000000..686d4cf
--- /dev/null
+++ b/test/unit/toolchain_make_variables/toolchain_make_variables_test.bzl
@@ -0,0 +1,126 @@
+"""Tests for make variables provided by `rust_toolchain`"""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest")
+load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test")
+load("//test/unit:common.bzl", "assert_action_mnemonic", "assert_env_value")
+
+_ENV = {
+    "ENV_VAR_CARGO": "$(CARGO)",
+    "ENV_VAR_RUSTC": "$(RUSTC)",
+    "ENV_VAR_RUSTDOC": "$(RUSTDOC)",
+    "ENV_VAR_RUSTFMT": "$(RUSTFMT)",
+    "ENV_VAR_RUST_DEFAULT_EDITION": "$(RUST_DEFAULT_EDITION)",
+    "ENV_VAR_RUST_SYSROOT": "$(RUST_SYSROOT)",
+}
+
+def _rustc_env_variable_expansion_test_impl(ctx):
+    env = analysistest.begin(ctx)
+    target = analysistest.target_under_test(env)
+    action = target.actions[0]
+
+    assert_action_mnemonic(
+        env = env,
+        action = action,
+        mnemonic = "Rustc",
+    )
+
+    toolchain = ctx.attr._current_rust_toolchain[platform_common.ToolchainInfo]
+
+    expected_values = {
+        "ENV_VAR_CARGO": toolchain.cargo.path,
+        "ENV_VAR_RUSTC": toolchain.rustc.path,
+        "ENV_VAR_RUSTDOC": toolchain.rust_doc.path,
+        "ENV_VAR_RUSTFMT": toolchain.rustfmt.path,
+        "ENV_VAR_RUST_DEFAULT_EDITION": toolchain.default_edition or "",
+        "ENV_VAR_RUST_SYSROOT": toolchain.sysroot,
+    }
+
+    for key in _ENV:
+        assert_env_value(
+            env = env,
+            action = action,
+            key = key,
+            value = expected_values[key],
+        )
+
+    return analysistest.end(env)
+
+rustc_env_variable_expansion_test = analysistest.make(
+    impl = _rustc_env_variable_expansion_test_impl,
+    attrs = {
+        "_current_rust_toolchain": attr.label(
+            doc = "The currently registered rust toolchain",
+            default = Label("//rust/toolchain:current_rust_toolchain"),
+        ),
+    },
+)
+
+def _define_targets():
+    rust_library(
+        name = "library",
+        srcs = ["main.rs"],
+        toolchains = ["//rust/toolchain:current_rust_toolchain"],
+        rustc_env = _ENV,
+        edition = "2018",
+    )
+
+    rust_binary(
+        name = "binary",
+        srcs = ["main.rs"],
+        toolchains = ["//rust/toolchain:current_rust_toolchain"],
+        rustc_env = _ENV,
+        edition = "2018",
+    )
+
+    rust_test(
+        name = "integration_test",
+        srcs = ["main.rs"],
+        toolchains = ["//rust/toolchain:current_rust_toolchain"],
+        rustc_env = _ENV,
+        edition = "2018",
+    )
+
+    rust_test(
+        name = "unit_test",
+        crate = "library",
+        toolchains = ["//rust/toolchain:current_rust_toolchain"],
+        rustc_env = _ENV,
+    )
+
+def toolchain_make_variable_test_suite(name):
+    """Defines a test suite
+
+    Args:
+        name (str): The name of the test suite
+    """
+    _define_targets()
+
+    rustc_env_variable_expansion_test(
+        name = "rustc_env_variable_expansion_library_test",
+        target_under_test = ":library",
+    )
+
+    rustc_env_variable_expansion_test(
+        name = "rustc_env_variable_expansion_binary_test",
+        target_under_test = ":binary",
+    )
+
+    rustc_env_variable_expansion_test(
+        name = "rustc_env_variable_expansion_integration_test_test",
+        target_under_test = ":integration_test",
+    )
+
+    rustc_env_variable_expansion_test(
+        name = "rustc_env_variable_expansion_unit_test_test",
+        target_under_test = ":unit_test",
+    )
+
+    native.test_suite(
+        name = name,
+        tests = [
+            ":rustc_env_variable_expansion_library_test",
+            ":rustc_env_variable_expansion_binary_test",
+            ":rustc_env_variable_expansion_integration_test_test",
+            ":rustc_env_variable_expansion_unit_test_test",
+        ],
+    )