rust-analyzer: Factor aliases into the project (#2709)

Fixes #2707
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
index 2113b98..6a03df1 100644
--- a/WORKSPACE.bazel
+++ b/WORKSPACE.bazel
@@ -87,3 +87,7 @@
     strip_prefix = "rules_testing-0.6.0",
     url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.6.0/rules_testing-v0.6.0.tar.gz",
 )
+
+load("//test/3rdparty/crates:crates.bzl", test_crate_repositories = "crate_repositories")
+
+test_crate_repositories()
diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl
index a8735de..4c45401 100644
--- a/proto/prost/private/prost.bzl
+++ b/proto/prost/private/prost.bzl
@@ -259,6 +259,7 @@
     cfgs = ["test", "debug_assertions"]
 
     rust_analyzer_info = write_rust_analyzer_spec_file(ctx, ctx.rule.attr, ctx.label, RustAnalyzerInfo(
+        aliases = {},
         crate = dep_variant_info.crate_info,
         cfgs = cfgs,
         env = dep_variant_info.crate_info.rustc_env,
diff --git a/rust/private/providers.bzl b/rust/private/providers.bzl
index c2770dc..97c4500 100644
--- a/rust/private/providers.bzl
+++ b/rust/private/providers.bzl
@@ -157,6 +157,7 @@
 RustAnalyzerInfo = provider(
     doc = "RustAnalyzerInfo holds rust crate metadata for targets",
     fields = {
+        "aliases": "Dict[RustAnalyzerInfo, String]: Replacement names these targets should be known as in Rust code",
         "build_info": "BuildInfo: build info for this crate if present",
         "cfgs": "List[String]: features or other compilation `--cfg` settings",
         "crate": "CrateInfo: Crate information.",
diff --git a/rust/private/rust_analyzer.bzl b/rust/private/rust_analyzer.bzl
index 2682d96..b972206 100644
--- a/rust/private/rust_analyzer.bzl
+++ b/rust/private/rust_analyzer.bzl
@@ -47,6 +47,7 @@
     crate_spec = ctx.actions.declare_file("{}.rust_analyzer_crate_spec.json".format(owner.name))
 
     rust_analyzer_info = RustAnalyzerInfo(
+        aliases = base_info.aliases,
         crate = base_info.crate,
         cfgs = base_info.cfgs,
         env = base_info.env,
@@ -70,6 +71,21 @@
 
     return rust_analyzer_info
 
+def _accumulate_rust_analyzer_info(dep_infos_to_accumulate, label_index_to_accumulate, dep):
+    if dep == None:
+        return
+    if RustAnalyzerInfo in dep:
+        label_index_to_accumulate[dep.label] = dep[RustAnalyzerInfo]
+        dep_infos_to_accumulate.append(dep[RustAnalyzerInfo])
+    if RustAnalyzerGroupInfo in dep:
+        for expanded_dep in dep[RustAnalyzerGroupInfo].deps:
+            label_index_to_accumulate[expanded_dep.crate.owner] = expanded_dep
+            dep_infos_to_accumulate.append(expanded_dep)
+
+def _accumulate_rust_analyzer_infos(dep_infos_to_accumulate, label_index_to_accumulate, deps_attr):
+    for dep in deps_attr:
+        _accumulate_rust_analyzer_info(dep_infos_to_accumulate, label_index_to_accumulate, dep)
+
 def _rust_analyzer_aspect_impl(target, ctx):
     if (rust_common.crate_info not in target and
         rust_common.test_crate_info not in target and
@@ -91,37 +107,18 @@
 
     build_info = None
     dep_infos = []
-    if hasattr(ctx.rule.attr, "deps"):
-        for dep in ctx.rule.attr.deps:
-            # Save BuildInfo if we find any (for build script output)
-            if BuildInfo in dep:
-                build_info = dep[BuildInfo]
-        dep_infos = [dep[RustAnalyzerInfo] for dep in ctx.rule.attr.deps if RustAnalyzerInfo in dep]
+    labels_to_rais = {}
 
-        group_infos = [dep[RustAnalyzerGroupInfo] for dep in ctx.rule.attr.deps if RustAnalyzerGroupInfo in dep]
-        for group_info in group_infos:
-            dep_infos.extend(group_info.deps)
+    for dep in getattr(ctx.rule.attr, "deps", []):
+        # Save BuildInfo if we find any (for build script output)
+        if BuildInfo in dep:
+            build_info = dep[BuildInfo]
 
-    if hasattr(ctx.rule.attr, "proc_macro_deps"):
-        dep_infos += [dep[RustAnalyzerInfo] for dep in ctx.rule.attr.proc_macro_deps if RustAnalyzerInfo in dep]
+    _accumulate_rust_analyzer_infos(dep_infos, labels_to_rais, getattr(ctx.rule.attr, "deps", []))
+    _accumulate_rust_analyzer_infos(dep_infos, labels_to_rais, getattr(ctx.rule.attr, "proc_macro_deps", []))
 
-        group_infos = [dep[RustAnalyzerGroupInfo] for dep in ctx.rule.attr.proc_macro_deps if RustAnalyzerGroupInfo in dep]
-        for group_info in group_infos:
-            dep_infos.extend(group_info.deps)
-
-    if hasattr(ctx.rule.attr, "crate") and ctx.rule.attr.crate != None:
-        if RustAnalyzerInfo in ctx.rule.attr.crate:
-            dep_infos.append(ctx.rule.attr.crate[RustAnalyzerInfo])
-
-        if RustAnalyzerGroupInfo in ctx.rule.attr.crate:
-            dep_infos.extend(ctx.rule.attr.crate[RustAnalyzerGroupInfo])
-
-    if hasattr(ctx.rule.attr, "actual") and ctx.rule.attr.actual != None:
-        if RustAnalyzerInfo in ctx.rule.attr.actual:
-            dep_infos.append(ctx.rule.attr.actual[RustAnalyzerInfo])
-
-        if RustAnalyzerGroupInfo in ctx.rule.attr.actual:
-            dep_infos.extend(ctx.rule.attr.actual[RustAnalyzerGroupInfo])
+    _accumulate_rust_analyzer_info(dep_infos, labels_to_rais, getattr(ctx.rule.attr, "crate", None))
+    _accumulate_rust_analyzer_info(dep_infos, labels_to_rais, getattr(ctx.rule.attr, "actual", None))
 
     if rust_common.crate_group_info in target:
         return [RustAnalyzerGroupInfo(deps = dep_infos)]
@@ -132,7 +129,13 @@
     else:
         fail("Unexpected target type: {}".format(target))
 
+    aliases = {}
+    for aliased_target, aliased_name in getattr(ctx.rule.attr, "aliases", {}).items():
+        if aliased_target.label in labels_to_rais:
+            aliases[labels_to_rais[aliased_target.label]] = aliased_name
+
     rust_analyzer_info = write_rust_analyzer_spec_file(ctx, ctx.rule.attr, ctx.label, RustAnalyzerInfo(
+        aliases = aliases,
         crate = crate_info,
         cfgs = cfgs,
         env = crate_info.rustc_env,
@@ -249,6 +252,7 @@
     # the crate being processed, we don't add it as a dependency to itself. This is
     # common and expected - `rust_test.crate` pointing to the `rust_library`.
     crate["deps"] = [_crate_id(dep.crate) for dep in info.deps if _crate_id(dep.crate) != crate_id]
+    crate["aliases"] = {_crate_id(alias_target.crate): alias_name for alias_target, alias_name in info.aliases.items()}
     crate["cfg"] = info.cfgs
     crate["target"] = find_toolchain(ctx).target_triple.str
     if info.proc_macro_dylib_path != None:
diff --git a/test/3rdparty/BUILD.bazel b/test/3rdparty/BUILD.bazel
new file mode 100644
index 0000000..82fa7dd
--- /dev/null
+++ b/test/3rdparty/BUILD.bazel
@@ -0,0 +1,23 @@
+load("//crate_universe:defs.bzl", "crate", "crates_vendor")
+
+package(default_visibility = ["//visibility:public"])
+
+crates_vendor(
+    name = "crates_vendor",
+    mode = "remote",
+    packages = {
+        "serde": crate.spec(
+            features = ["derive"],
+            version = "1",
+        ),
+        "serde_json": crate.spec(
+            version = "1",
+        ),
+    },
+    # Short for 'test 3rdparty'. Keep this short to reduce the risk to
+    # bump into absolute path length issues on Windows. See:
+    # https://github.com/bazelbuild/rules_rust/issues/1120
+    repository_name = "t3p",
+    tags = ["manual"],
+    vendor_path = "crates",
+)
diff --git a/test/3rdparty/crates/BUILD.bazel b/test/3rdparty/crates/BUILD.bazel
new file mode 100644
index 0000000..91b079a
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.bazel
@@ -0,0 +1,44 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+package(default_visibility = ["//visibility:public"])
+
+exports_files(
+    [
+        "cargo-bazel.json",
+        "crates.bzl",
+        "defs.bzl",
+    ] + glob(
+        include = ["*.bazel"],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "srcs",
+    srcs = glob(
+        include = [
+            "*.bazel",
+            "*.bzl",
+        ],
+        allow_empty = True,
+    ),
+)
+
+# Workspace Member Dependencies
+alias(
+    name = "serde",
+    actual = "@t3p__serde-1.0.203//:serde",
+    tags = ["manual"],
+)
+
+alias(
+    name = "serde_json",
+    actual = "@t3p__serde_json-1.0.117//:serde_json",
+    tags = ["manual"],
+)
diff --git a/test/3rdparty/crates/BUILD.itoa-1.0.11.bazel b/test/3rdparty/crates/BUILD.itoa-1.0.11.bazel
new file mode 100644
index 0000000..db0f149
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.itoa-1.0.11.bazel
@@ -0,0 +1,81 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "itoa",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_root = "src/lib.rs",
+    edition = "2018",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=itoa",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.11",
+)
diff --git a/test/3rdparty/crates/BUILD.proc-macro2-1.0.85.bazel b/test/3rdparty/crates/BUILD.proc-macro2-1.0.85.bazel
new file mode 100644
index 0000000..395a611
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.proc-macro2-1.0.85.bazel
@@ -0,0 +1,134 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "proc_macro2",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "proc-macro",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2021",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=proc-macro2",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.85",
+    deps = [
+        "@t3p__proc-macro2-1.0.85//:build_script_build",
+        "@t3p__unicode-ident-1.0.12//:unicode_ident",
+    ],
+)
+
+cargo_build_script(
+    name = "_bs",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    crate_features = [
+        "proc-macro",
+    ],
+    crate_name = "build_script_build",
+    crate_root = "build.rs",
+    data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    edition = "2021",
+    pkg_name = "proc-macro2",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=proc-macro2",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    version = "1.0.85",
+    visibility = ["//visibility:private"],
+)
+
+alias(
+    name = "build_script_build",
+    actual = ":_bs",
+    tags = ["manual"],
+)
diff --git a/test/3rdparty/crates/BUILD.quote-1.0.36.bazel b/test/3rdparty/crates/BUILD.quote-1.0.36.bazel
new file mode 100644
index 0000000..9f7ecf5
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.quote-1.0.36.bazel
@@ -0,0 +1,87 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "quote",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "proc-macro",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2018",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=quote",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.36",
+    deps = [
+        "@t3p__proc-macro2-1.0.85//:proc_macro2",
+    ],
+)
diff --git a/test/3rdparty/crates/BUILD.ryu-1.0.18.bazel b/test/3rdparty/crates/BUILD.ryu-1.0.18.bazel
new file mode 100644
index 0000000..c0125cb
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.ryu-1.0.18.bazel
@@ -0,0 +1,81 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "ryu",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_root = "src/lib.rs",
+    edition = "2018",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=ryu",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.18",
+)
diff --git a/test/3rdparty/crates/BUILD.serde-1.0.203.bazel b/test/3rdparty/crates/BUILD.serde-1.0.203.bazel
new file mode 100644
index 0000000..5b9af89
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.serde-1.0.203.bazel
@@ -0,0 +1,142 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "serde",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "default",
+        "derive",
+        "serde_derive",
+        "std",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2018",
+    proc_macro_deps = [
+        "@t3p__serde_derive-1.0.203//:serde_derive",
+    ],
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=serde",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.203",
+    deps = [
+        "@t3p__serde-1.0.203//:build_script_build",
+    ],
+)
+
+cargo_build_script(
+    name = "_bs",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    crate_features = [
+        "default",
+        "derive",
+        "serde_derive",
+        "std",
+    ],
+    crate_name = "build_script_build",
+    crate_root = "build.rs",
+    data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    edition = "2018",
+    pkg_name = "serde",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=serde",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    version = "1.0.203",
+    visibility = ["//visibility:private"],
+)
+
+alias(
+    name = "build_script_build",
+    actual = ":_bs",
+    tags = ["manual"],
+)
diff --git a/test/3rdparty/crates/BUILD.serde_derive-1.0.203.bazel b/test/3rdparty/crates/BUILD.serde_derive-1.0.203.bazel
new file mode 100644
index 0000000..fa3be7f
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.serde_derive-1.0.203.bazel
@@ -0,0 +1,89 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_proc_macro")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_proc_macro(
+    name = "serde_derive",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "default",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2015",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=serde_derive",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.203",
+    deps = [
+        "@t3p__proc-macro2-1.0.85//:proc_macro2",
+        "@t3p__quote-1.0.36//:quote",
+        "@t3p__syn-2.0.66//:syn",
+    ],
+)
diff --git a/test/3rdparty/crates/BUILD.serde_json-1.0.117.bazel b/test/3rdparty/crates/BUILD.serde_json-1.0.117.bazel
new file mode 100644
index 0000000..f8cdde0
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.serde_json-1.0.117.bazel
@@ -0,0 +1,138 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "serde_json",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "default",
+        "std",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2021",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=serde_json",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.117",
+    deps = [
+        "@t3p__itoa-1.0.11//:itoa",
+        "@t3p__ryu-1.0.18//:ryu",
+        "@t3p__serde-1.0.203//:serde",
+        "@t3p__serde_json-1.0.117//:build_script_build",
+    ],
+)
+
+cargo_build_script(
+    name = "_bs",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    crate_features = [
+        "default",
+        "std",
+    ],
+    crate_name = "build_script_build",
+    crate_root = "build.rs",
+    data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    edition = "2021",
+    pkg_name = "serde_json",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=serde_json",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    version = "1.0.117",
+    visibility = ["//visibility:private"],
+)
+
+alias(
+    name = "build_script_build",
+    actual = ":_bs",
+    tags = ["manual"],
+)
diff --git a/test/3rdparty/crates/BUILD.syn-2.0.66.bazel b/test/3rdparty/crates/BUILD.syn-2.0.66.bazel
new file mode 100644
index 0000000..4e55cd8
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.syn-2.0.66.bazel
@@ -0,0 +1,93 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "syn",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_features = [
+        "clone-impls",
+        "derive",
+        "parsing",
+        "printing",
+        "proc-macro",
+    ],
+    crate_root = "src/lib.rs",
+    edition = "2021",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=syn",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "2.0.66",
+    deps = [
+        "@t3p__proc-macro2-1.0.85//:proc_macro2",
+        "@t3p__quote-1.0.36//:quote",
+        "@t3p__unicode-ident-1.0.12//:unicode_ident",
+    ],
+)
diff --git a/test/3rdparty/crates/BUILD.unicode-ident-1.0.12.bazel b/test/3rdparty/crates/BUILD.unicode-ident-1.0.12.bazel
new file mode 100644
index 0000000..ea68afd
--- /dev/null
+++ b/test/3rdparty/crates/BUILD.unicode-ident-1.0.12.bazel
@@ -0,0 +1,81 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_library(
+    name = "unicode_ident",
+    srcs = glob(
+        include = ["**/*.rs"],
+        allow_empty = True,
+    ),
+    compile_data = glob(
+        include = ["**"],
+        allow_empty = True,
+        exclude = [
+            "**/* *",
+            ".tmp_git_root/**/*",
+            "BUILD",
+            "BUILD.bazel",
+            "WORKSPACE",
+            "WORKSPACE.bazel",
+        ],
+    ),
+    crate_root = "src/lib.rs",
+    edition = "2018",
+    rustc_flags = [
+        "--cap-lints=allow",
+    ],
+    tags = [
+        "cargo-bazel",
+        "crate-name=unicode-ident",
+        "manual",
+        "noclippy",
+        "norustfmt",
+    ],
+    target_compatible_with = select({
+        "@rules_rust//rust/platform:aarch64-apple-darwin": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios": [],
+        "@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
+        "@rules_rust//rust/platform:aarch64-fuchsia": [],
+        "@rules_rust//rust/platform:aarch64-linux-android": [],
+        "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
+        "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:armv7-linux-androideabi": [],
+        "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
+        "@rules_rust//rust/platform:i686-apple-darwin": [],
+        "@rules_rust//rust/platform:i686-linux-android": [],
+        "@rules_rust//rust/platform:i686-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:i686-unknown-freebsd": [],
+        "@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
+        "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:thumbv7em-none-eabi": [],
+        "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
+        "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
+        "@rules_rust//rust/platform:wasm32-wasi": [],
+        "@rules_rust//rust/platform:x86_64-apple-darwin": [],
+        "@rules_rust//rust/platform:x86_64-apple-ios": [],
+        "@rules_rust//rust/platform:x86_64-fuchsia": [],
+        "@rules_rust//rust/platform:x86_64-linux-android": [],
+        "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
+        "@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
+        "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
+        "@rules_rust//rust/platform:x86_64-unknown-none": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    version = "1.0.12",
+)
diff --git a/test/3rdparty/crates/alias_rules.bzl b/test/3rdparty/crates/alias_rules.bzl
new file mode 100644
index 0000000..14b04c1
--- /dev/null
+++ b/test/3rdparty/crates/alias_rules.bzl
@@ -0,0 +1,47 @@
+"""Alias that transitions its target to `compilation_mode=opt`.  Use `transition_alias="opt"` to enable."""
+
+load("@rules_cc//cc:defs.bzl", "CcInfo")
+load("@rules_rust//rust:rust_common.bzl", "COMMON_PROVIDERS")
+
+def _transition_alias_impl(ctx):
+    # `ctx.attr.actual` is a list of 1 item due to the transition
+    providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS]
+    if CcInfo in ctx.attr.actual[0]:
+        providers.append(ctx.attr.actual[0][CcInfo])
+    return providers
+
+def _change_compilation_mode(compilation_mode):
+    def _change_compilation_mode_impl(_settings, _attr):
+        return {
+            "//command_line_option:compilation_mode": compilation_mode,
+        }
+
+    return transition(
+        implementation = _change_compilation_mode_impl,
+        inputs = [],
+        outputs = [
+            "//command_line_option:compilation_mode",
+        ],
+    )
+
+def _transition_alias_rule(compilation_mode):
+    return rule(
+        implementation = _transition_alias_impl,
+        provides = COMMON_PROVIDERS,
+        attrs = {
+            "actual": attr.label(
+                mandatory = True,
+                doc = "`rust_library()` target to transition to `compilation_mode=opt`.",
+                providers = COMMON_PROVIDERS,
+                cfg = _change_compilation_mode(compilation_mode),
+            ),
+            "_allowlist_function_transition": attr.label(
+                default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+            ),
+        },
+        doc = "Transitions a Rust library crate to the `compilation_mode=opt`.",
+    )
+
+transition_alias_dbg = _transition_alias_rule("dbg")
+transition_alias_fastbuild = _transition_alias_rule("fastbuild")
+transition_alias_opt = _transition_alias_rule("opt")
diff --git a/test/3rdparty/crates/crates.bzl b/test/3rdparty/crates/crates.bzl
new file mode 100644
index 0000000..dbf2516
--- /dev/null
+++ b/test/3rdparty/crates/crates.bzl
@@ -0,0 +1,32 @@
+###############################################################################
+# @generated
+# This file is auto-generated by the cargo-bazel tool.
+#
+# DO NOT MODIFY: Local changes may be replaced in future executions.
+###############################################################################
+"""Rules for defining repositories for remote `crates_vendor` repositories"""
+
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+
+# buildifier: disable=bzl-visibility
+load("@rules_rust//crate_universe/private:crates_vendor.bzl", "crates_vendor_remote_repository")
+
+# buildifier: disable=bzl-visibility
+load("@rules_rust//test/3rdparty/crates:defs.bzl", _crate_repositories = "crate_repositories")
+
+def crate_repositories():
+    """Generates repositories for vendored crates.
+
+    Returns:
+      A list of repos visible to the module through the module extension.
+    """
+    maybe(
+        crates_vendor_remote_repository,
+        name = "t3p",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.bazel"),
+        defs_module = Label("@rules_rust//test/3rdparty/crates:defs.bzl"),
+    )
+
+    direct_deps = [struct(repo = "t3p", is_dev_dep = False)]
+    direct_deps.extend(_crate_repositories())
+    return direct_deps
diff --git a/test/3rdparty/crates/defs.bzl b/test/3rdparty/crates/defs.bzl
new file mode 100644
index 0000000..6f698ed
--- /dev/null
+++ b/test/3rdparty/crates/defs.bzl
@@ -0,0 +1,499 @@
+###############################################################################
+# @generated
+# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
+# regenerate this file, run the following:
+#
+#     bazel run @//test/3rdparty:crates_vendor
+###############################################################################
+"""
+# `crates_repository` API
+
+- [aliases](#aliases)
+- [crate_deps](#crate_deps)
+- [all_crate_deps](#all_crate_deps)
+- [crate_repositories](#crate_repositories)
+
+"""
+
+load("@bazel_skylib//lib:selects.bzl", "selects")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+
+###############################################################################
+# MACROS API
+###############################################################################
+
+# An identifier that represent common dependencies (unconditional).
+_COMMON_CONDITION = ""
+
+def _flatten_dependency_maps(all_dependency_maps):
+    """Flatten a list of dependency maps into one dictionary.
+
+    Dependency maps have the following structure:
+
+    ```python
+    DEPENDENCIES_MAP = {
+        # The first key in the map is a Bazel package
+        # name of the workspace this file is defined in.
+        "workspace_member_package": {
+
+            # Not all dependencies are supported for all platforms.
+            # the condition key is the condition required to be true
+            # on the host platform.
+            "condition": {
+
+                # An alias to a crate target.     # The label of the crate target the
+                # Aliases are only crate names.   # package name refers to.
+                "package_name":                   "@full//:label",
+            }
+        }
+    }
+    ```
+
+    Args:
+        all_dependency_maps (list): A list of dicts as described above
+
+    Returns:
+        dict: A dictionary as described above
+    """
+    dependencies = {}
+
+    for workspace_deps_map in all_dependency_maps:
+        for pkg_name, conditional_deps_map in workspace_deps_map.items():
+            if pkg_name not in dependencies:
+                non_frozen_map = dict()
+                for key, values in conditional_deps_map.items():
+                    non_frozen_map.update({key: dict(values.items())})
+                dependencies.setdefault(pkg_name, non_frozen_map)
+                continue
+
+            for condition, deps_map in conditional_deps_map.items():
+                # If the condition has not been recorded, do so and continue
+                if condition not in dependencies[pkg_name]:
+                    dependencies[pkg_name].setdefault(condition, dict(deps_map.items()))
+                    continue
+
+                # Alert on any miss-matched dependencies
+                inconsistent_entries = []
+                for crate_name, crate_label in deps_map.items():
+                    existing = dependencies[pkg_name][condition].get(crate_name)
+                    if existing and existing != crate_label:
+                        inconsistent_entries.append((crate_name, existing, crate_label))
+                    dependencies[pkg_name][condition].update({crate_name: crate_label})
+
+    return dependencies
+
+def crate_deps(deps, package_name = None):
+    """Finds the fully qualified label of the requested crates for the package where this macro is called.
+
+    Args:
+        deps (list): The desired list of crate targets.
+        package_name (str, optional): The package name of the set of dependencies to look up.
+            Defaults to `native.package_name()`.
+
+    Returns:
+        list: A list of labels to generated rust targets (str)
+    """
+
+    if not deps:
+        return []
+
+    if package_name == None:
+        package_name = native.package_name()
+
+    # Join both sets of dependencies
+    dependencies = _flatten_dependency_maps([
+        _NORMAL_DEPENDENCIES,
+        _NORMAL_DEV_DEPENDENCIES,
+        _PROC_MACRO_DEPENDENCIES,
+        _PROC_MACRO_DEV_DEPENDENCIES,
+        _BUILD_DEPENDENCIES,
+        _BUILD_PROC_MACRO_DEPENDENCIES,
+    ]).pop(package_name, {})
+
+    # Combine all conditional packages so we can easily index over a flat list
+    # TODO: Perhaps this should actually return select statements and maintain
+    # the conditionals of the dependencies
+    flat_deps = {}
+    for deps_set in dependencies.values():
+        for crate_name, crate_label in deps_set.items():
+            flat_deps.update({crate_name: crate_label})
+
+    missing_crates = []
+    crate_targets = []
+    for crate_target in deps:
+        if crate_target not in flat_deps:
+            missing_crates.append(crate_target)
+        else:
+            crate_targets.append(flat_deps[crate_target])
+
+    if missing_crates:
+        fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format(
+            missing_crates,
+            package_name,
+            dependencies,
+        ))
+
+    return crate_targets
+
+def all_crate_deps(
+        normal = False,
+        normal_dev = False,
+        proc_macro = False,
+        proc_macro_dev = False,
+        build = False,
+        build_proc_macro = False,
+        package_name = None):
+    """Finds the fully qualified label of all requested direct crate dependencies \
+    for the package where this macro is called.
+
+    If no parameters are set, all normal dependencies are returned. Setting any one flag will
+    otherwise impact the contents of the returned list.
+
+    Args:
+        normal (bool, optional): If True, normal dependencies are included in the
+            output list.
+        normal_dev (bool, optional): If True, normal dev dependencies will be
+            included in the output list..
+        proc_macro (bool, optional): If True, proc_macro dependencies are included
+            in the output list.
+        proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are
+            included in the output list.
+        build (bool, optional): If True, build dependencies are included
+            in the output list.
+        build_proc_macro (bool, optional): If True, build proc_macro dependencies are
+            included in the output list.
+        package_name (str, optional): The package name of the set of dependencies to look up.
+            Defaults to `native.package_name()` when unset.
+
+    Returns:
+        list: A list of labels to generated rust targets (str)
+    """
+
+    if package_name == None:
+        package_name = native.package_name()
+
+    # Determine the relevant maps to use
+    all_dependency_maps = []
+    if normal:
+        all_dependency_maps.append(_NORMAL_DEPENDENCIES)
+    if normal_dev:
+        all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES)
+    if proc_macro:
+        all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)
+    if proc_macro_dev:
+        all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES)
+    if build:
+        all_dependency_maps.append(_BUILD_DEPENDENCIES)
+    if build_proc_macro:
+        all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES)
+
+    # Default to always using normal dependencies
+    if not all_dependency_maps:
+        all_dependency_maps.append(_NORMAL_DEPENDENCIES)
+
+    dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None)
+
+    if not dependencies:
+        if dependencies == None:
+            fail("Tried to get all_crate_deps for package " + package_name + " but that package had no Cargo.toml file")
+        else:
+            return []
+
+    crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values())
+    for condition, deps in dependencies.items():
+        crate_deps += selects.with_or({
+            tuple(_CONDITIONS[condition]): deps.values(),
+            "//conditions:default": [],
+        })
+
+    return crate_deps
+
+def aliases(
+        normal = False,
+        normal_dev = False,
+        proc_macro = False,
+        proc_macro_dev = False,
+        build = False,
+        build_proc_macro = False,
+        package_name = None):
+    """Produces a map of Crate alias names to their original label
+
+    If no dependency kinds are specified, `normal` and `proc_macro` are used by default.
+    Setting any one flag will otherwise determine the contents of the returned dict.
+
+    Args:
+        normal (bool, optional): If True, normal dependencies are included in the
+            output list.
+        normal_dev (bool, optional): If True, normal dev dependencies will be
+            included in the output list..
+        proc_macro (bool, optional): If True, proc_macro dependencies are included
+            in the output list.
+        proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are
+            included in the output list.
+        build (bool, optional): If True, build dependencies are included
+            in the output list.
+        build_proc_macro (bool, optional): If True, build proc_macro dependencies are
+            included in the output list.
+        package_name (str, optional): The package name of the set of dependencies to look up.
+            Defaults to `native.package_name()` when unset.
+
+    Returns:
+        dict: The aliases of all associated packages
+    """
+    if package_name == None:
+        package_name = native.package_name()
+
+    # Determine the relevant maps to use
+    all_aliases_maps = []
+    if normal:
+        all_aliases_maps.append(_NORMAL_ALIASES)
+    if normal_dev:
+        all_aliases_maps.append(_NORMAL_DEV_ALIASES)
+    if proc_macro:
+        all_aliases_maps.append(_PROC_MACRO_ALIASES)
+    if proc_macro_dev:
+        all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES)
+    if build:
+        all_aliases_maps.append(_BUILD_ALIASES)
+    if build_proc_macro:
+        all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES)
+
+    # Default to always using normal aliases
+    if not all_aliases_maps:
+        all_aliases_maps.append(_NORMAL_ALIASES)
+        all_aliases_maps.append(_PROC_MACRO_ALIASES)
+
+    aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None)
+
+    if not aliases:
+        return dict()
+
+    common_items = aliases.pop(_COMMON_CONDITION, {}).items()
+
+    # If there are only common items in the dictionary, immediately return them
+    if not len(aliases.keys()) == 1:
+        return dict(common_items)
+
+    # Build a single select statement where each conditional has accounted for the
+    # common set of aliases.
+    crate_aliases = {"//conditions:default": dict(common_items)}
+    for condition, deps in aliases.items():
+        condition_triples = _CONDITIONS[condition]
+        for triple in condition_triples:
+            if triple in crate_aliases:
+                crate_aliases[triple].update(deps)
+            else:
+                crate_aliases.update({triple: dict(deps.items() + common_items)})
+
+    return select(crate_aliases)
+
+###############################################################################
+# WORKSPACE MEMBER DEPS AND ALIASES
+###############################################################################
+
+_NORMAL_DEPENDENCIES = {
+    "": {
+        _COMMON_CONDITION: {
+            "serde": Label("@t3p__serde-1.0.203//:serde"),
+            "serde_json": Label("@t3p__serde_json-1.0.117//:serde_json"),
+        },
+    },
+}
+
+_NORMAL_ALIASES = {
+    "": {
+        _COMMON_CONDITION: {
+        },
+    },
+}
+
+_NORMAL_DEV_DEPENDENCIES = {
+    "": {
+    },
+}
+
+_NORMAL_DEV_ALIASES = {
+    "": {
+    },
+}
+
+_PROC_MACRO_DEPENDENCIES = {
+    "": {
+    },
+}
+
+_PROC_MACRO_ALIASES = {
+    "": {
+    },
+}
+
+_PROC_MACRO_DEV_DEPENDENCIES = {
+    "": {
+    },
+}
+
+_PROC_MACRO_DEV_ALIASES = {
+    "": {
+    },
+}
+
+_BUILD_DEPENDENCIES = {
+    "": {
+    },
+}
+
+_BUILD_ALIASES = {
+    "": {
+    },
+}
+
+_BUILD_PROC_MACRO_DEPENDENCIES = {
+    "": {
+    },
+}
+
+_BUILD_PROC_MACRO_ALIASES = {
+    "": {
+    },
+}
+
+_CONDITIONS = {
+    "aarch64-apple-darwin": ["@rules_rust//rust/platform:aarch64-apple-darwin"],
+    "aarch64-apple-ios": ["@rules_rust//rust/platform:aarch64-apple-ios"],
+    "aarch64-apple-ios-sim": ["@rules_rust//rust/platform:aarch64-apple-ios-sim"],
+    "aarch64-fuchsia": ["@rules_rust//rust/platform:aarch64-fuchsia"],
+    "aarch64-linux-android": ["@rules_rust//rust/platform:aarch64-linux-android"],
+    "aarch64-pc-windows-msvc": ["@rules_rust//rust/platform:aarch64-pc-windows-msvc"],
+    "aarch64-unknown-linux-gnu": ["@rules_rust//rust/platform:aarch64-unknown-linux-gnu"],
+    "aarch64-unknown-nixos-gnu": ["@rules_rust//rust/platform:aarch64-unknown-nixos-gnu"],
+    "aarch64-unknown-nto-qnx710": ["@rules_rust//rust/platform:aarch64-unknown-nto-qnx710"],
+    "arm-unknown-linux-gnueabi": ["@rules_rust//rust/platform:arm-unknown-linux-gnueabi"],
+    "armv7-linux-androideabi": ["@rules_rust//rust/platform:armv7-linux-androideabi"],
+    "armv7-unknown-linux-gnueabi": ["@rules_rust//rust/platform:armv7-unknown-linux-gnueabi"],
+    "i686-apple-darwin": ["@rules_rust//rust/platform:i686-apple-darwin"],
+    "i686-linux-android": ["@rules_rust//rust/platform:i686-linux-android"],
+    "i686-pc-windows-msvc": ["@rules_rust//rust/platform:i686-pc-windows-msvc"],
+    "i686-unknown-freebsd": ["@rules_rust//rust/platform:i686-unknown-freebsd"],
+    "i686-unknown-linux-gnu": ["@rules_rust//rust/platform:i686-unknown-linux-gnu"],
+    "powerpc-unknown-linux-gnu": ["@rules_rust//rust/platform:powerpc-unknown-linux-gnu"],
+    "riscv32imc-unknown-none-elf": ["@rules_rust//rust/platform:riscv32imc-unknown-none-elf"],
+    "riscv64gc-unknown-none-elf": ["@rules_rust//rust/platform:riscv64gc-unknown-none-elf"],
+    "s390x-unknown-linux-gnu": ["@rules_rust//rust/platform:s390x-unknown-linux-gnu"],
+    "thumbv7em-none-eabi": ["@rules_rust//rust/platform:thumbv7em-none-eabi"],
+    "thumbv8m.main-none-eabi": ["@rules_rust//rust/platform:thumbv8m.main-none-eabi"],
+    "wasm32-unknown-unknown": ["@rules_rust//rust/platform:wasm32-unknown-unknown"],
+    "wasm32-wasi": ["@rules_rust//rust/platform:wasm32-wasi"],
+    "x86_64-apple-darwin": ["@rules_rust//rust/platform:x86_64-apple-darwin"],
+    "x86_64-apple-ios": ["@rules_rust//rust/platform:x86_64-apple-ios"],
+    "x86_64-fuchsia": ["@rules_rust//rust/platform:x86_64-fuchsia"],
+    "x86_64-linux-android": ["@rules_rust//rust/platform:x86_64-linux-android"],
+    "x86_64-pc-windows-msvc": ["@rules_rust//rust/platform:x86_64-pc-windows-msvc"],
+    "x86_64-unknown-freebsd": ["@rules_rust//rust/platform:x86_64-unknown-freebsd"],
+    "x86_64-unknown-linux-gnu": ["@rules_rust//rust/platform:x86_64-unknown-linux-gnu"],
+    "x86_64-unknown-nixos-gnu": ["@rules_rust//rust/platform:x86_64-unknown-nixos-gnu"],
+    "x86_64-unknown-none": ["@rules_rust//rust/platform:x86_64-unknown-none"],
+}
+
+###############################################################################
+
+def crate_repositories():
+    """A macro for defining repositories for all generated crates.
+
+    Returns:
+      A list of repos visible to the module through the module extension.
+    """
+    maybe(
+        http_archive,
+        name = "t3p__itoa-1.0.11",
+        sha256 = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/itoa/1.0.11/download"],
+        strip_prefix = "itoa-1.0.11",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.itoa-1.0.11.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__proc-macro2-1.0.85",
+        sha256 = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/proc-macro2/1.0.85/download"],
+        strip_prefix = "proc-macro2-1.0.85",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.proc-macro2-1.0.85.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__quote-1.0.36",
+        sha256 = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/quote/1.0.36/download"],
+        strip_prefix = "quote-1.0.36",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.quote-1.0.36.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__ryu-1.0.18",
+        sha256 = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/ryu/1.0.18/download"],
+        strip_prefix = "ryu-1.0.18",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.ryu-1.0.18.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__serde-1.0.203",
+        sha256 = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/serde/1.0.203/download"],
+        strip_prefix = "serde-1.0.203",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.serde-1.0.203.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__serde_derive-1.0.203",
+        sha256 = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/serde_derive/1.0.203/download"],
+        strip_prefix = "serde_derive-1.0.203",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.serde_derive-1.0.203.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__serde_json-1.0.117",
+        sha256 = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/serde_json/1.0.117/download"],
+        strip_prefix = "serde_json-1.0.117",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.serde_json-1.0.117.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__syn-2.0.66",
+        sha256 = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/syn/2.0.66/download"],
+        strip_prefix = "syn-2.0.66",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.syn-2.0.66.bazel"),
+    )
+
+    maybe(
+        http_archive,
+        name = "t3p__unicode-ident-1.0.12",
+        sha256 = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b",
+        type = "tar.gz",
+        urls = ["https://static.crates.io/crates/unicode-ident/1.0.12/download"],
+        strip_prefix = "unicode-ident-1.0.12",
+        build_file = Label("@rules_rust//test/3rdparty/crates:BUILD.unicode-ident-1.0.12.bazel"),
+    )
+
+    return [
+        struct(repo = "t3p__serde-1.0.203", is_dev_dep = False),
+        struct(repo = "t3p__serde_json-1.0.117", is_dev_dep = False),
+    ]
diff --git a/test/rust_analyzer/aspect_traversal_test/BUILD.bazel b/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
index 899fa0e..faabf82 100644
--- a/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
+++ b/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
@@ -4,8 +4,14 @@
 rust_library(
     name = "mylib",
     srcs = ["mylib.rs"],
+    aliases = {
+        ":renamed_proc_macro_dep": "shorter_name",
+    },
     edition = "2018",
-    proc_macro_deps = [":proc_macro_dep"],
+    proc_macro_deps = [
+        ":proc_macro_dep",
+        ":renamed_proc_macro_dep",
+    ],
     deps = [
         ":alias_dep",
         ":custom_alias_dep",
@@ -81,6 +87,12 @@
     edition = "2018",
 )
 
+rust_proc_macro(
+    name = "renamed_proc_macro_dep",
+    srcs = ["renamed_proc_macro_dep.rs"],
+    edition = "2018",
+)
+
 rust_test(
     name = "rust_project_json_test",
     srcs = ["rust_project_json_test.rs"],
@@ -91,4 +103,8 @@
     # contexts outside of `//test/rust_analyzer:rust_analyzer_test`. Run
     # that target to execute this test.
     tags = ["manual"],
+    deps = [
+        "@rules_rust//test/3rdparty/crates:serde",
+        "@rules_rust//test/3rdparty/crates:serde_json",
+    ],
 )
diff --git a/test/rust_analyzer/aspect_traversal_test/renamed_proc_macro_dep.rs b/test/rust_analyzer/aspect_traversal_test/renamed_proc_macro_dep.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/rust_analyzer/aspect_traversal_test/renamed_proc_macro_dep.rs
@@ -0,0 +1 @@
+
diff --git a/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs b/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
index 6ecbf0d..0ffb9b7 100644
--- a/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
+++ b/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
@@ -1,5 +1,8 @@
 #[cfg(test)]
 mod tests {
+    use serde::Deserialize;
+
+    use std::collections::BTreeSet;
     use std::env;
     use std::path::PathBuf;
 
@@ -28,4 +31,52 @@
             );
         }
     }
+
+    #[test]
+    fn test_aliases_are_applied() {
+        let rust_project_path = PathBuf::from(env::var("RUST_PROJECT_JSON").unwrap());
+
+        let content = std::fs::read_to_string(&rust_project_path)
+            .unwrap_or_else(|_| panic!("couldn't open {:?}", &rust_project_path));
+
+        let project: Project =
+            serde_json::from_str(&content).expect("Failed to deserialize project JSON");
+
+        let renamed_proc_macro_dep_index = project
+            .crates
+            .iter()
+            .enumerate()
+            .find(|(_, krate)| krate.display_name == "renamed_proc_macro_dep")
+            .map(|(index, _)| index)
+            .unwrap();
+        let krate = project
+            .crates
+            .iter()
+            .find(|krate| krate.display_name == "mylib")
+            .unwrap();
+        let dep = krate
+            .deps
+            .iter()
+            .find(|dep| dep.krate == renamed_proc_macro_dep_index)
+            .unwrap();
+        assert_eq!(dep.name, "shorter_name");
+    }
+
+    #[derive(Deserialize)]
+    struct Project {
+        crates: Vec<Crate>,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
+    struct Crate {
+        display_name: String,
+        deps: BTreeSet<Dep>,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
+    struct Dep {
+        #[serde(rename = "crate")]
+        krate: usize,
+        name: String,
+    }
 }
diff --git a/test/rust_analyzer/rust_analyzer_test_runner.sh b/test/rust_analyzer/rust_analyzer_test_runner.sh
index 08f9bf3..e602a6f 100755
--- a/test/rust_analyzer/rust_analyzer_test_runner.sh
+++ b/test/rust_analyzer/rust_analyzer_test_runner.sh
@@ -31,6 +31,10 @@
 rust_repositories()
 load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
 rust_analyzer_dependencies()
+
+load("@rules_rust//test/3rdparty/crates:crates.bzl", test_crate_repositories = "crate_repositories")
+
+test_crate_repositories()
 EOF
 
     cat <<EOF >"${new_workspace}/.bazelrc"
diff --git a/tools/rust_analyzer/aquery.rs b/tools/rust_analyzer/aquery.rs
index 3a65628..1228238 100644
--- a/tools/rust_analyzer/aquery.rs
+++ b/tools/rust_analyzer/aquery.rs
@@ -39,6 +39,7 @@
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)]
 #[serde(deny_unknown_fields)]
 pub struct CrateSpec {
+    pub aliases: BTreeMap<String, String>,
     pub crate_id: String,
     pub display_name: String,
     pub edition: String,
@@ -219,6 +220,7 @@
     fn consolidate_lib_then_test_specs() {
         let crate_specs = vec![
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib".into(),
                 edition: "2018".into(),
@@ -233,6 +235,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-extra_test_dep.rs".into(),
                 display_name: "extra_test_dep".into(),
                 edition: "2018".into(),
@@ -247,6 +250,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-lib_dep.rs".into(),
                 display_name: "lib_dep".into(),
                 edition: "2018".into(),
@@ -261,6 +265,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib_test".into(),
                 edition: "2018".into(),
@@ -280,6 +285,7 @@
             consolidate_crate_specs(crate_specs).unwrap(),
             BTreeSet::from([
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-mylib.rs".into(),
                     display_name: "mylib".into(),
                     edition: "2018".into(),
@@ -294,6 +300,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-extra_test_dep.rs".into(),
                     display_name: "extra_test_dep".into(),
                     edition: "2018".into(),
@@ -308,6 +315,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-lib_dep.rs".into(),
                     display_name: "lib_dep".into(),
                     edition: "2018".into(),
@@ -329,6 +337,7 @@
     fn consolidate_test_then_lib_specs() {
         let crate_specs = vec![
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib_test".into(),
                 edition: "2018".into(),
@@ -343,6 +352,7 @@
                 crate_type: "bin".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib".into(),
                 edition: "2018".into(),
@@ -357,6 +367,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-extra_test_dep.rs".into(),
                 display_name: "extra_test_dep".into(),
                 edition: "2018".into(),
@@ -371,6 +382,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-lib_dep.rs".into(),
                 display_name: "lib_dep".into(),
                 edition: "2018".into(),
@@ -390,6 +402,7 @@
             consolidate_crate_specs(crate_specs).unwrap(),
             BTreeSet::from([
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-mylib.rs".into(),
                     display_name: "mylib".into(),
                     edition: "2018".into(),
@@ -404,6 +417,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-extra_test_dep.rs".into(),
                     display_name: "extra_test_dep".into(),
                     edition: "2018".into(),
@@ -418,6 +432,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-lib_dep.rs".into(),
                     display_name: "lib_dep".into(),
                     edition: "2018".into(),
@@ -444,6 +459,7 @@
         // mylib in mylib2.rs.
         let crate_specs = vec![
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib".into(),
                 edition: "2018".into(),
@@ -458,6 +474,7 @@
                 crate_type: "rlib".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib_test".into(),
                 edition: "2018".into(),
@@ -472,6 +489,7 @@
                 crate_type: "bin".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib.rs".into(),
                 display_name: "mylib_main".into(),
                 edition: "2018".into(),
@@ -486,6 +504,7 @@
                 crate_type: "bin".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-mylib2.rs".into(),
                 display_name: "mylib2".into(),
                 edition: "2018".into(),
@@ -506,6 +525,7 @@
                 consolidate_crate_specs(perm).unwrap(),
                 BTreeSet::from([
                     CrateSpec {
+                        aliases: BTreeMap::new(),
                         crate_id: "ID-mylib.rs".into(),
                         display_name: "mylib".into(),
                         edition: "2018".into(),
@@ -520,6 +540,7 @@
                         crate_type: "rlib".into(),
                     },
                     CrateSpec {
+                        aliases: BTreeMap::new(),
                         crate_id: "ID-mylib2.rs".into(),
                         display_name: "mylib2".into(),
                         edition: "2018".into(),
@@ -545,6 +566,7 @@
         // when explicitly building that target.
         let crate_specs = vec![
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-myproc_macro.rs".into(),
                 display_name: "myproc_macro".into(),
                 edition: "2018".into(),
@@ -562,6 +584,7 @@
                 crate_type: "proc_macro".into(),
             },
             CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-myproc_macro.rs".into(),
                 display_name: "myproc_macro".into(),
                 edition: "2018".into(),
@@ -583,6 +606,7 @@
             assert_eq!(
                 consolidate_crate_specs(perm).unwrap(),
                 BTreeSet::from([CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-myproc_macro.rs".into(),
                     display_name: "myproc_macro".into(),
                     edition: "2018".into(),
diff --git a/tools/rust_analyzer/rust_project.rs b/tools/rust_analyzer/rust_project.rs
index d64496d..09ad723 100644
--- a/tools/rust_analyzer/rust_project.rs
+++ b/tools/rust_analyzer/rust_project.rs
@@ -137,14 +137,16 @@
                                 .get(dep)
                                 .expect("failed to find dependency on second lookup");
                             let dep_crate = &project.crates[crate_index];
-                            Dependency {
-                                crate_index,
-                                name: dep_crate
+                            let name = if let Some(alias) = c.aliases.get(dep) {
+                                alias.clone()
+                            } else {
+                                dep_crate
                                     .display_name
                                     .as_ref()
                                     .expect("all crates should have display_name")
-                                    .clone(),
-                            }
+                                    .clone()
+                            };
+                            Dependency { crate_index, name }
                         })
                         .collect(),
                     is_workspace_member: Some(c.is_workspace_member),
@@ -278,6 +280,7 @@
             "sysroot",
             "sysroot_src",
             &BTreeSet::from([CrateSpec {
+                aliases: BTreeMap::new(),
                 crate_id: "ID-example".into(),
                 display_name: "example".into(),
                 edition: "2018".into(),
@@ -309,6 +312,7 @@
             "sysroot_src",
             &BTreeSet::from([
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-example".into(),
                     display_name: "example".into(),
                     edition: "2018".into(),
@@ -323,6 +327,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-dep_a".into(),
                     display_name: "dep_a".into(),
                     edition: "2018".into(),
@@ -337,6 +342,7 @@
                     crate_type: "rlib".into(),
                 },
                 CrateSpec {
+                    aliases: BTreeMap::new(),
                     crate_id: "ID-dep_b".into(),
                     display_name: "dep_b".into(),
                     edition: "2018".into(),
diff --git a/util/repin_all.sh b/util/repin_all.sh
index 7ac9130..5f29c18 100755
--- a/util/repin_all.sh
+++ b/util/repin_all.sh
@@ -6,6 +6,7 @@
 
 # Re-generates all files which may need to be re-generated after changing crate_universe.
 bazel run //crate_universe/3rdparty:crates_vendor
+bazel run //test/3rdparty:crates_vendor
 bazel run //tools/rust_analyzer/3rdparty:crates_vendor
 
 for d in examples/crate_universe/vendor_*; do