Summary
Distributed ThinLTO currently opts rlib and lib crates in, but the CcInfo they export does not provide the shared non-LTO backends that Bazel requires when a statically linked C++ test uses the shared-backend ThinLTO mode.
Reproduction
Using the rules_rust revision bundled by rules_rs v0.0.107 (9ec12231debd8a929faafa0c014a8a897e4899c0), enable:
--features=thin_lto
--features=thin_lto_linkstatic_tests_use_shared_nonlto_backends
Then build a static cc_test or cc_binary that transitively depends on a Rust rlib. Bazel analysis fails before actions run:
Statically linked test target requires non-LTO backends for its library inputs,
but library input ... does not specify shared_non_lto_backends
The failing LibraryToLink contains the rlib object and pic_lto_compilation_context, but its pic_shared_non_lto_backends is empty.
Why this matters
The shared non-LTO backend feature avoids rerunning ThinLTO indexing and codegen for every static C++ test. Disabling it avoids this check but materially increases build work; disabling thin_lto loses ThinLTO entirely. The public //rust/settings:lto setting does not control this path because distributed ThinLTO is selected from the C++ thin_lto feature.
Expected behavior
rlib/lib crates that participate in distributed ThinLTO should either:
- provide the shared non-LTO backends required by their exported
CcInfo, or
- be excluded from distributed ThinLTO when that provider cannot be produced.
An optional public setting to choose eligible crate types would let users make this tradeoff deliberately, but the provider inconsistency itself appears to be a correctness bug.
Workaround
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -910,7 +910,7 @@ def _supports_distributed_thin_lto(ctx, toolchain, crate_info):
"""Whether `crate_info` can participate in distributed ThinLTO."""
return (
- crate_info.type in ("bin", "lib", "rlib") and
+ crate_info.type == "bin" and
toolchain.target_arch not in ("wasm32", "wasm64") and
not toolchain._bootstrapping and
not is_no_std(ctx, toolchain, crate_info.is_test)
)
Summary
Distributed ThinLTO currently opts
rlibandlibcrates in, but theCcInfothey export does not provide the shared non-LTO backends that Bazel requires when a statically linked C++ test uses the shared-backend ThinLTO mode.Reproduction
Using the
rules_rustrevision bundled byrules_rsv0.0.107 (9ec12231debd8a929faafa0c014a8a897e4899c0), enable:Then build a static
cc_testorcc_binarythat transitively depends on a Rustrlib. Bazel analysis fails before actions run:The failing
LibraryToLinkcontains the rlib object andpic_lto_compilation_context, but itspic_shared_non_lto_backendsis empty.Why this matters
The shared non-LTO backend feature avoids rerunning ThinLTO indexing and codegen for every static C++ test. Disabling it avoids this check but materially increases build work; disabling
thin_ltoloses ThinLTO entirely. The public//rust/settings:ltosetting does not control this path because distributed ThinLTO is selected from the C++thin_ltofeature.Expected behavior
rlib/libcrates that participate in distributed ThinLTO should either:CcInfo, orAn optional public setting to choose eligible crate types would let users make this tradeoff deliberately, but the provider inconsistency itself appears to be a correctness bug.
Workaround