Support linking Rust code into a C++ binary

This is based on a version of my upstream PR:
https://github.com/bazelbuild/rules_rust/pull/1350

Change-Id: Ica7097c10666d2e0017336cf7d81420605238493
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/WORKSPACE b/WORKSPACE
index 50aad8c..79af5a3 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -841,6 +841,7 @@
 
 rust_toolchain_repository(
     name = "rust",
+    allocator_library = "@//tools/rust:forward_allocator",
     edition = "2021",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [
diff --git a/build_tests/BUILD b/build_tests/BUILD
index 29a1275..24fdad8 100644
--- a/build_tests/BUILD
+++ b/build_tests/BUILD
@@ -178,3 +178,16 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [":ts_test"],
 )
+
+rust_library(
+    name = "rust_in_cc_rs",
+    srcs = ["rust_in_cc.rs"],
+    target_compatible_with = ["@platforms//os:linux"],
+)
+
+cc_test(
+    name = "rust_in_cc",
+    srcs = ["rust_in_cc.cc"],
+    target_compatible_with = ["@platforms//os:linux"],
+    deps = [":rust_in_cc_rs"],
+)
diff --git a/build_tests/rust_in_cc.cc b/build_tests/rust_in_cc.cc
new file mode 100644
index 0000000..9c13b1b
--- /dev/null
+++ b/build_tests/rust_in_cc.cc
@@ -0,0 +1,19 @@
+// A very minimal rust_library linked into a cc_binary to make sure we still get
+// the allocator symbols linked in.
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern "C" int32_t rust_return5();
+
+extern "C" uint8_t c_return5() { return 5; }
+
+extern "C" void c_take5(uint8_t *) {}
+
+int main() {
+  const int rust_result = rust_return5();
+  printf("Rust says: %d\n", rust_result);
+  if (rust_result != 5) {
+    return 1;
+  }
+}
diff --git a/build_tests/rust_in_cc.rs b/build_tests/rust_in_cc.rs
new file mode 100644
index 0000000..0810609
--- /dev/null
+++ b/build_tests/rust_in_cc.rs
@@ -0,0 +1,19 @@
+extern "C" {
+    fn c_return5() -> u8;
+    fn c_take5(x: *mut u8);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rust_return5() -> i32 {
+    let layout = std::alloc::Layout::from_size_align(1, 1).unwrap();
+    let a = std::alloc::alloc(layout);
+    *a = c_return5();
+    // Do something so the compiler can't optimize out the alloc+free pair, which would invalidate
+    // this test.
+    if *a != 5 {
+        c_take5(a);
+    } else {
+        std::alloc::dealloc(a, layout);
+    }
+    5
+}
diff --git a/third_party/rules_rust/.bazelci/presubmit.yml b/third_party/rules_rust/.bazelci/presubmit.yml
index 1e59628..b948e0a 100644
--- a/third_party/rules_rust/.bazelci/presubmit.yml
+++ b/third_party/rules_rust/.bazelci/presubmit.yml
@@ -20,6 +20,8 @@
   - "//vendor_local_pkgs:crates_vendor"
   - "//vendor_remote_manifests:crates_vendor_manifests"
   - "//vendor_remote_pkgs:crates_vendor_pkgs"
+cc_binary_example_targets: &cc_binary_example_targets
+  - "//..."
 tasks:
   ubuntu2004:
     build_targets: *default_linux_targets
@@ -297,6 +299,52 @@
       - "//..."
     test_targets:
       - "//..."
+  cc_binary_examples_ubuntu2004:
+    name: Crate Universe Examples
+    platform: ubuntu2004
+    working_directory: examples/cc_binary
+    run_targets: *cc_binary_example_targets
+    build_targets:
+      - "//..."
+    test_targets:
+      - "//..."
+    build_flags: *aspects_flags
+  cc_binary_rbe_ubuntu1604:
+    name: Crate Universe Examples
+    platform: rbe_ubuntu1604
+    working_directory: examples/cc_binary
+    shell_commands:
+      - sed -i 's/^# load("@bazelci_rules/load("@bazelci_rules/' WORKSPACE.bazel
+      - sed -i 's/^# rbe_preconfig/rbe_preconfig/' WORKSPACE.bazel
+    run_targets: *cc_binary_example_targets
+    build_targets:
+      - "//..."
+    test_targets:
+      - "//..."
+    build_flags: *aspects_flags
+  cc_binary_examples_macos:
+    name: Crate Universe Examples
+    platform: macos
+    working_directory: examples/cc_binary
+    run_targets: *cc_binary_example_targets
+    build_targets:
+      - "//..."
+    test_targets:
+      - "//..."
+    build_flags: *aspects_flags
+  cc_binary_examples_windows:
+    name: Crate Universe Examples
+    platform: windows
+    working_directory: examples/cc_binary
+    batch_commands:
+      - echo startup --windows_enable_symlinks >> user.bazelrc
+      - echo build --enable_runfiles >> user.bazelrc  # this is not enabled by default on windows and is necessary for the cargo build scripts
+    run_targets: *cc_binary_example_targets
+    build_flags: *aspects_flags
+    build_targets:
+      - "//..."
+    test_targets:
+      - "//..."
 buildifier:
   version: latest
   warnings: "all"
diff --git a/third_party/rules_rust/docs/flatten.md b/third_party/rules_rust/docs/flatten.md
index f650bc9..0f82ad7 100644
--- a/third_party/rules_rust/docs/flatten.md
+++ b/third_party/rules_rust/docs/flatten.md
@@ -1141,9 +1141,9 @@
 ## rust_toolchain_repository
 
 <pre>
-rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>, <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>,
-                          <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>, <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>,
-                          <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
+rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-allocator_library">allocator_library</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>,
+                          <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>, <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>,
+                          <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>, <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
 </pre>
 
 Composes a single workspace containing the toolchain components for compiling on a given platform to a series of target platforms.
@@ -1156,6 +1156,7 @@
 | Name  | Description | Type | Mandatory | Default |
 | :------------- | :------------- | :------------- | :------------- | :------------- |
 | <a id="rust_toolchain_repository-name"></a>name |  A unique name for this repository.   | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required |  |
+| <a id="rust_toolchain_repository-allocator_library"></a>allocator_library |  Target that provides allocator functions when rust_library targets are embedded in a cc_binary.   | String | optional | "" |
 | <a id="rust_toolchain_repository-auth"></a>auth |  Auth object compatible with repository_ctx.download to use when downloading files. See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.   | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |
 | <a id="rust_toolchain_repository-dev_components"></a>dev_components |  Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly".   | Boolean | optional | False |
 | <a id="rust_toolchain_repository-edition"></a>edition |  The rust edition to be used by default.   | String | optional | "2018" |
@@ -1362,7 +1363,7 @@
 
 <pre>
 StdLibInfo(<a href="#StdLibInfo-alloc_files">alloc_files</a>, <a href="#StdLibInfo-between_alloc_and_core_files">between_alloc_and_core_files</a>, <a href="#StdLibInfo-between_core_and_std_files">between_core_and_std_files</a>, <a href="#StdLibInfo-core_files">core_files</a>,
-           <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
+           <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
 </pre>
 
 A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
@@ -1377,6 +1378,7 @@
 | <a id="StdLibInfo-between_core_and_std_files"></a>between_core_and_std_files |  List[File]: <code>.a</code> files related to all modules except <code>adler</code>, <code>alloc</code>, <code>compiler_builtins</code>, <code>core</code>, and <code>std</code>.    |
 | <a id="StdLibInfo-core_files"></a>core_files |  List[File]: <code>.a</code> files related to the <code>core</code> and <code>adler</code> modules    |
 | <a id="StdLibInfo-dot_a_files"></a>dot_a_files |  Depset[File]: Generated <code>.a</code> files    |
+| <a id="StdLibInfo-memchr_files"></a>memchr_files |  Depset[File]: <code>.a</code> files associated with the <code>memchr</code> module.    |
 | <a id="StdLibInfo-self_contained_files"></a>self_contained_files |  List[File]: All <code>.o</code> files from the <code>self-contained</code> directory.    |
 | <a id="StdLibInfo-srcs"></a>srcs |  List[Target]: All targets from the original <code>srcs</code> attribute.    |
 | <a id="StdLibInfo-std_files"></a>std_files |  Depset[File]: <code>.a</code> files associated with the <code>std</code> module.    |
@@ -1611,8 +1613,9 @@
 ## rust_repository_set
 
 <pre>
-rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>,
-                    <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>, <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
+rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-allocator_library">allocator_library</a>,
+                    <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>, <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>,
+                    <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
 </pre>
 
 Assembles a remote repository for the given toolchain params, produces a proxy repository     to contain the toolchain declaration, and registers the toolchains.
@@ -1629,6 +1632,7 @@
 | <a id="rust_repository_set-version"></a>version |  The version of the tool among "nightly", "beta', or an exact version.   |  none |
 | <a id="rust_repository_set-exec_triple"></a>exec_triple |  The Rust-style target that this compiler runs on   |  none |
 | <a id="rust_repository_set-include_rustc_srcs"></a>include_rustc_srcs |  Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.   |  <code>False</code> |
+| <a id="rust_repository_set-allocator_library"></a>allocator_library |  Target that provides allocator functions when rust_library targets are embedded in a cc_binary.   |  <code>None</code> |
 | <a id="rust_repository_set-extra_target_triples"></a>extra_target_triples |  Additional rust-style targets that this set of toolchains should support. Defaults to [].   |  <code>[]</code> |
 | <a id="rust_repository_set-iso_date"></a>iso_date |  The date of the tool. Defaults to None.   |  <code>None</code> |
 | <a id="rust_repository_set-rustfmt_version"></a>rustfmt_version |  The version of rustfmt to be associated with the toolchain. Defaults to None.   |  <code>None</code> |
diff --git a/third_party/rules_rust/docs/providers.md b/third_party/rules_rust/docs/providers.md
index 0a78246..f4aa819 100644
--- a/third_party/rules_rust/docs/providers.md
+++ b/third_party/rules_rust/docs/providers.md
@@ -68,7 +68,7 @@
 
 <pre>
 StdLibInfo(<a href="#StdLibInfo-alloc_files">alloc_files</a>, <a href="#StdLibInfo-between_alloc_and_core_files">between_alloc_and_core_files</a>, <a href="#StdLibInfo-between_core_and_std_files">between_core_and_std_files</a>, <a href="#StdLibInfo-core_files">core_files</a>,
-           <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
+           <a href="#StdLibInfo-dot_a_files">dot_a_files</a>, <a href="#StdLibInfo-memchr_files">memchr_files</a>, <a href="#StdLibInfo-self_contained_files">self_contained_files</a>, <a href="#StdLibInfo-srcs">srcs</a>, <a href="#StdLibInfo-std_files">std_files</a>, <a href="#StdLibInfo-std_rlibs">std_rlibs</a>)
 </pre>
 
 A collection of files either found within the `rust-stdlib` artifact or generated based on existing files.
@@ -83,6 +83,7 @@
 | <a id="StdLibInfo-between_core_and_std_files"></a>between_core_and_std_files |  List[File]: <code>.a</code> files related to all modules except <code>adler</code>, <code>alloc</code>, <code>compiler_builtins</code>, <code>core</code>, and <code>std</code>.    |
 | <a id="StdLibInfo-core_files"></a>core_files |  List[File]: <code>.a</code> files related to the <code>core</code> and <code>adler</code> modules    |
 | <a id="StdLibInfo-dot_a_files"></a>dot_a_files |  Depset[File]: Generated <code>.a</code> files    |
+| <a id="StdLibInfo-memchr_files"></a>memchr_files |  Depset[File]: <code>.a</code> files associated with the <code>memchr</code> module.    |
 | <a id="StdLibInfo-self_contained_files"></a>self_contained_files |  List[File]: All <code>.o</code> files from the <code>self-contained</code> directory.    |
 | <a id="StdLibInfo-srcs"></a>srcs |  List[Target]: All targets from the original <code>srcs</code> attribute.    |
 | <a id="StdLibInfo-std_files"></a>std_files |  Depset[File]: <code>.a</code> files associated with the <code>std</code> module.    |
diff --git a/third_party/rules_rust/docs/rust_repositories.md b/third_party/rules_rust/docs/rust_repositories.md
index 8f68ff7..27a6354 100644
--- a/third_party/rules_rust/docs/rust_repositories.md
+++ b/third_party/rules_rust/docs/rust_repositories.md
@@ -116,9 +116,9 @@
 ## rust_toolchain_repository
 
 <pre>
-rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>, <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>,
-                          <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>, <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>,
-                          <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
+rust_toolchain_repository(<a href="#rust_toolchain_repository-name">name</a>, <a href="#rust_toolchain_repository-allocator_library">allocator_library</a>, <a href="#rust_toolchain_repository-auth">auth</a>, <a href="#rust_toolchain_repository-dev_components">dev_components</a>, <a href="#rust_toolchain_repository-edition">edition</a>, <a href="#rust_toolchain_repository-exec_triple">exec_triple</a>,
+                          <a href="#rust_toolchain_repository-extra_target_triples">extra_target_triples</a>, <a href="#rust_toolchain_repository-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_toolchain_repository-iso_date">iso_date</a>, <a href="#rust_toolchain_repository-repo_mapping">repo_mapping</a>,
+                          <a href="#rust_toolchain_repository-rustfmt_version">rustfmt_version</a>, <a href="#rust_toolchain_repository-sha256s">sha256s</a>, <a href="#rust_toolchain_repository-toolchain_name_prefix">toolchain_name_prefix</a>, <a href="#rust_toolchain_repository-urls">urls</a>, <a href="#rust_toolchain_repository-version">version</a>)
 </pre>
 
 Composes a single workspace containing the toolchain components for compiling on a given platform to a series of target platforms.
@@ -131,6 +131,7 @@
 | Name  | Description | Type | Mandatory | Default |
 | :------------- | :------------- | :------------- | :------------- | :------------- |
 | <a id="rust_toolchain_repository-name"></a>name |  A unique name for this repository.   | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required |  |
+| <a id="rust_toolchain_repository-allocator_library"></a>allocator_library |  Target that provides allocator functions when rust_library targets are embedded in a cc_binary.   | String | optional | "" |
 | <a id="rust_toolchain_repository-auth"></a>auth |  Auth object compatible with repository_ctx.download to use when downloading files. See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.   | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |
 | <a id="rust_toolchain_repository-dev_components"></a>dev_components |  Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly".   | Boolean | optional | False |
 | <a id="rust_toolchain_repository-edition"></a>edition |  The rust edition to be used by default.   | String | optional | "2018" |
@@ -193,8 +194,9 @@
 ## rust_repository_set
 
 <pre>
-rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>,
-                    <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>, <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
+rust_repository_set(<a href="#rust_repository_set-name">name</a>, <a href="#rust_repository_set-version">version</a>, <a href="#rust_repository_set-exec_triple">exec_triple</a>, <a href="#rust_repository_set-include_rustc_srcs">include_rustc_srcs</a>, <a href="#rust_repository_set-allocator_library">allocator_library</a>,
+                    <a href="#rust_repository_set-extra_target_triples">extra_target_triples</a>, <a href="#rust_repository_set-iso_date">iso_date</a>, <a href="#rust_repository_set-rustfmt_version">rustfmt_version</a>, <a href="#rust_repository_set-edition">edition</a>, <a href="#rust_repository_set-dev_components">dev_components</a>, <a href="#rust_repository_set-sha256s">sha256s</a>,
+                    <a href="#rust_repository_set-urls">urls</a>, <a href="#rust_repository_set-auth">auth</a>, <a href="#rust_repository_set-register_toolchain">register_toolchain</a>)
 </pre>
 
 Assembles a remote repository for the given toolchain params, produces a proxy repository     to contain the toolchain declaration, and registers the toolchains.
@@ -211,6 +213,7 @@
 | <a id="rust_repository_set-version"></a>version |  The version of the tool among "nightly", "beta', or an exact version.   |  none |
 | <a id="rust_repository_set-exec_triple"></a>exec_triple |  The Rust-style target that this compiler runs on   |  none |
 | <a id="rust_repository_set-include_rustc_srcs"></a>include_rustc_srcs |  Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.   |  <code>False</code> |
+| <a id="rust_repository_set-allocator_library"></a>allocator_library |  Target that provides allocator functions when rust_library targets are embedded in a cc_binary.   |  <code>None</code> |
 | <a id="rust_repository_set-extra_target_triples"></a>extra_target_triples |  Additional rust-style targets that this set of toolchains should support. Defaults to [].   |  <code>[]</code> |
 | <a id="rust_repository_set-iso_date"></a>iso_date |  The date of the tool. Defaults to None.   |  <code>None</code> |
 | <a id="rust_repository_set-rustfmt_version"></a>rustfmt_version |  The version of rustfmt to be associated with the toolchain. Defaults to None.   |  <code>None</code> |
diff --git a/third_party/rules_rust/rust/private/providers.bzl b/third_party/rules_rust/rust/private/providers.bzl
index b471ac0..de6d314 100644
--- a/third_party/rules_rust/rust/private/providers.bzl
+++ b/third_party/rules_rust/rust/private/providers.bzl
@@ -89,6 +89,7 @@
         "between_core_and_std_files": "List[File]: `.a` files related to all modules except `adler`, `alloc`, `compiler_builtins`, `core`, and `std`.",
         "core_files": "List[File]: `.a` files related to the `core` and `adler` modules",
         "dot_a_files": "Depset[File]: Generated `.a` files",
+        "memchr_files": "Depset[File]: `.a` files associated with the `memchr` module.",
         "self_contained_files": "List[File]: All `.o` files from the `self-contained` directory.",
         "srcs": "List[Target]: All targets from the original `srcs` attribute.",
         "std_files": "Depset[File]: `.a` files associated with the `std` module.",
diff --git a/third_party/rules_rust/rust/private/repository_utils.bzl b/third_party/rules_rust/rust/private/repository_utils.bzl
index b6c83aa..1c33331 100644
--- a/third_party/rules_rust/rust/private/repository_utils.bzl
+++ b/third_party/rules_rust/rust/private/repository_utils.bzl
@@ -191,6 +191,7 @@
     clippy_driver = "@{workspace_name}//:clippy_driver_bin",
     rustc_lib = "@{workspace_name}//:rustc_lib",
     rustc_srcs = {rustc_srcs},
+    allocator_library = {allocator_library},
     binary_ext = "{binary_ext}",
     staticlib_ext = "{staticlib_ext}",
     dylib_ext = "{dylib_ext}",
@@ -209,6 +210,7 @@
         exec_triple,
         target_triple,
         include_rustc_srcs,
+        allocator_library,
         default_edition,
         include_rustfmt,
         stdlib_linkflags = None):
@@ -220,6 +222,7 @@
         exec_triple (str): The rust-style target that this compiler runs on
         target_triple (str): The rust-style target triple of the tool
         include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.
+        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
         default_edition (str): Default Rust edition.
         include_rustfmt (bool): Whether rustfmt is present in the toolchain.
         stdlib_linkflags (list, optional): Overriden flags needed for linking to rust
@@ -240,6 +243,9 @@
     rustfmt_label = "None"
     if include_rustfmt:
         rustfmt_label = "\"@{workspace_name}//:rustfmt_bin\"".format(workspace_name = workspace_name)
+    allocator_library_label = "None"
+    if allocator_library:
+        allocator_library_label = "\"{allocator_library}\"".format(allocator_library = allocator_library)
 
     return _build_file_for_rust_toolchain_template.format(
         toolchain_name = name,
@@ -248,6 +254,7 @@
         staticlib_ext = system_to_staticlib_ext(system),
         dylib_ext = system_to_dylib_ext(system),
         rustc_srcs = rustc_srcs,
+        allocator_library = allocator_library_label,
         stdlib_linkflags = stdlib_linkflags,
         system = system,
         default_edition = default_edition,
@@ -404,6 +411,7 @@
         ),
         exec_triple = ctx.attr.exec_triple,
         include_rustc_srcs = should_include_rustc_srcs(ctx),
+        allocator_library = ctx.attr.allocator_library,
         target_triple = target_triple,
         stdlib_linkflags = stdlib_linkflags,
         workspace_name = ctx.attr.name,
diff --git a/third_party/rules_rust/rust/repositories.bzl b/third_party/rules_rust/rust/repositories.bzl
index 99f2f51..de5cb47 100644
--- a/third_party/rules_rust/rust/repositories.bzl
+++ b/third_party/rules_rust/rust/repositories.bzl
@@ -64,6 +64,7 @@
         dev_components = False,
         edition = None,
         include_rustc_srcs = False,
+        allocator_library = None,
         iso_date = None,
         register_toolchains = True,
         rustfmt_version = None,
@@ -94,6 +95,7 @@
         edition (str, optional): The rust edition to be used by default (2015, 2018 (default), or 2021)
         include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support.
             See [rust_toolchain_repository.include_rustc_srcs](#rust_toolchain_repository-include_rustc_srcs). for more details
+        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
         iso_date (str, optional): The date of the nightly or beta release (ignored if the version is a specific version).
         register_toolchains (bool): If true, repositories will be generated to produce and register `rust_toolchain` targets.
         rustfmt_version (str, optional): The version of rustfmt. Either "nightly", "beta", or an exact version. Defaults to `version` if not specified.
@@ -117,6 +119,7 @@
             exec_triple = exec_triple,
             extra_target_triples = extra_target_triples,
             include_rustc_srcs = include_rustc_srcs,
+            allocator_library = allocator_library,
             iso_date = iso_date,
             register_toolchain = register_toolchains,
             rustfmt_version = rustfmt_version,
@@ -191,6 +194,9 @@
         "selection from toolchain fetching."
     ),
     attrs = {
+        "allocator_library": attr.string(
+            doc = "Target that provides allocator functions when rust_library targets are embedded in a cc_binary.",
+        ),
         "auth": attr.string_dict(
             doc = (
                 "Auth object compatible with repository_ctx.download to use when downloading files. " +
@@ -276,6 +282,7 @@
         version,
         exec_triple,
         include_rustc_srcs = False,
+        allocator_library = None,
         extra_target_triples = [],
         iso_date = None,
         rustfmt_version = None,
@@ -296,6 +303,7 @@
         version (str): The version of the tool among "nightly", "beta', or an exact version.
         exec_triple (str): The Rust-style target that this compiler runs on
         include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.
+        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
         extra_target_triples (list, optional): Additional rust-style targets that this set of
             toolchains should support. Defaults to [].
         iso_date (str, optional): The date of the tool. Defaults to None.
@@ -316,6 +324,7 @@
         name = name,
         exec_triple = exec_triple,
         include_rustc_srcs = include_rustc_srcs,
+        allocator_library = allocator_library,
         extra_target_triples = extra_target_triples,
         iso_date = iso_date,
         toolchain_name_prefix = DEFAULT_TOOLCHAIN_NAME_PREFIX,
diff --git a/third_party/rules_rust/rust/toolchain.bzl b/third_party/rules_rust/rust/toolchain.bzl
index 687e0df..083991a 100644
--- a/third_party/rules_rust/rust/toolchain.bzl
+++ b/third_party/rules_rust/rust/toolchain.bzl
@@ -11,6 +11,7 @@
     core_files = []
     between_core_and_std_files = []
     std_files = []
+    memchr_files = []
     alloc_files = []
     self_contained_files = [
         file
@@ -35,13 +36,14 @@
         between_core_and_std_files = [
             f
             for f in dot_a_files
-            if "alloc" not in f.basename and "compiler_builtins" not in f.basename and "core" not in f.basename and "adler" not in f.basename and "std" not in f.basename
+            if "alloc" not in f.basename and "compiler_builtins" not in f.basename and "core" not in f.basename and "adler" not in f.basename and "std" not in f.basename and "memchr" not in f.basename
         ]
+        memchr_files = [f for f in dot_a_files if "memchr" in f.basename]
         std_files = [f for f in dot_a_files if "std" in f.basename]
 
-        partitioned_files_len = len(alloc_files) + len(between_alloc_and_core_files) + len(core_files) + len(between_core_and_std_files) + len(std_files)
+        partitioned_files_len = len(alloc_files) + len(between_alloc_and_core_files) + len(core_files) + len(between_core_and_std_files) + len(memchr_files) + len(std_files)
         if partitioned_files_len != len(dot_a_files):
-            partitioned = alloc_files + between_alloc_and_core_files + core_files + between_core_and_std_files + std_files
+            partitioned = alloc_files + between_alloc_and_core_files + core_files + between_core_and_std_files + memchr_files + std_files
             for f in sorted(partitioned):
                 # buildifier: disable=print
                 print("File partitioned: {}".format(f.basename))
@@ -58,6 +60,7 @@
             core_files = core_files,
             between_core_and_std_files = between_core_and_std_files,
             std_files = std_files,
+            memchr_files = memchr_files,
             alloc_files = alloc_files,
             self_contained_files = self_contained_files,
             srcs = ctx.attr.srcs,
@@ -168,12 +171,20 @@
                 for f in filtered_between_core_and_std_files
                 if "panic_abort" not in f.basename
             ]
+        memchr_inputs = depset(
+            [
+                _ltl(f, ctx, cc_toolchain, feature_configuration)
+                for f in rust_stdlib_info.memchr_files
+            ],
+            transitive = [core_inputs],
+            order = "topological",
+        )
         between_core_and_std_inputs = depset(
             [
                 _ltl(f, ctx, cc_toolchain, feature_configuration)
                 for f in filtered_between_core_and_std_files
             ],
-            transitive = [core_inputs],
+            transitive = [memchr_inputs],
             order = "topological",
         )
         std_inputs = depset(
@@ -185,20 +196,20 @@
             order = "topological",
         )
 
-        link_inputs = cc_common.create_linker_input(
+        link_inputs = [depset([cc_common.create_linker_input(
             owner = rust_std.label,
             libraries = std_inputs,
-        )
+        )])]
 
-        allocator_inputs = None
+        allocator_inputs = []
         if allocator_library:
-            allocator_inputs = [allocator_library[CcInfo].linking_context.linker_inputs]
+            allocator_inputs = allocator_library[CcInfo].linking_context.linker_inputs.to_list()
 
         cc_infos.append(CcInfo(
             linking_context = cc_common.create_linking_context(
                 linker_inputs = depset(
-                    [link_inputs],
-                    transitive = allocator_inputs,
+                    allocator_inputs,
+                    transitive = link_inputs,
                     order = "topological",
                 ),
             ),
diff --git a/tools/rust/BUILD b/tools/rust/BUILD
index fccc3e4..4d9e4d6 100644
--- a/tools/rust/BUILD
+++ b/tools/rust/BUILD
@@ -132,3 +132,9 @@
     ],
 )
 '''
+
+cc_library(
+    name = "forward_allocator",
+    srcs = ["forward_allocator.c"],
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/rust/forward_allocator.c b/tools/rust/forward_allocator.c
new file mode 100644
index 0000000..3e6ba96
--- /dev/null
+++ b/tools/rust/forward_allocator.c
@@ -0,0 +1,46 @@
+#include <stdint.h>
+
+// This file has some exciting magic to get Rust code linking in a cc_binary.
+// The Rust compiler generates some similar symbol aliases when it links, so we
+// have to do it manually.
+//
+// It is intended to be used in rust_toolchain.allocator_library.
+//
+// https://github.com/rust-lang/rust/blob/master/library/alloc/src/alloc.rs
+// and https://github.com/rust-lang/rust/blob/master/library/std/src/alloc.rs
+// are the best source of docs I've found on these functions and variables.
+// https://doc.rust-lang.org/std/alloc/index.html talks about how this is
+// intended to be used.
+//
+// Also note
+// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html for
+// the sizes of the various integer types.
+//
+// This file strongly assumes that the default allocator is used. It will
+// not work with any other allocated switched in via `#[global_allocator]`.
+
+// New feature as of https://github.com/rust-lang/rust/pull/88098.
+uint8_t __rust_alloc_error_handler_should_panic = 0;
+
+uint8_t *__rdl_alloc(uintptr_t size, uintptr_t align);
+uint8_t *__rust_alloc(uintptr_t size, uintptr_t align) {
+  return __rdl_alloc(size, align);
+}
+void __rdl_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align);
+void __rust_dealloc(uint8_t *ptr, uintptr_t size, uintptr_t align) {
+  __rdl_dealloc(ptr, size, align);
+}
+uint8_t *__rdl_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
+                       uintptr_t new_size);
+uint8_t *__rust_realloc(uint8_t *ptr, uintptr_t old_size, uintptr_t align,
+                        uintptr_t new_size) {
+  return __rdl_realloc(ptr, old_size, align, new_size);
+}
+uint8_t *__rdl_alloc_zeroed(uintptr_t size, uintptr_t align);
+uint8_t *__rust_alloc_zeroed(uintptr_t size, uintptr_t align) {
+  return __rdl_alloc_zeroed(size, align);
+}
+void __rdl_oom(uintptr_t size, uintptr_t align);
+void __rust_alloc_error_handler(uintptr_t size, uintptr_t align) {
+  __rdl_oom(size, align);
+}