From f3ba350622f4afef370908df23685242af537ca3 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sat, 6 Sep 2025 10:37:29 -0400 Subject: [PATCH] propagate hax --- rust/private/rust.bzl | 63 +++++++++---------- rust/private/rustc.bzl | 2 +- rust/private/rustdoc_test.bzl | 7 ++- rust/private/utils.bzl | 22 +++++++ .../is_proc_macro_dep_test.bzl | 4 +- test/unit/rustdoc/rustdoc_unit_test.bzl | 4 +- 6 files changed, 60 insertions(+), 42 deletions(-) diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 3e9258c51e..de603e10f4 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -39,6 +39,7 @@ load( "generate_output_diagnostics", "get_edition", "get_import_macro_deps", + "partition_deps", "transform_deps", "transform_sources", ) @@ -53,31 +54,6 @@ def _assert_no_deprecated_attributes(_ctx): """ pass -def _assert_correct_dep_mapping(ctx): - """Forces a failure if proc_macro_deps and deps are mixed inappropriately - - Args: - ctx (ctx): The current rule's context object - """ - for dep in ctx.attr.deps: - if rust_common.crate_info in dep: - if dep[rust_common.crate_info].type == "proc-macro": - fail( - "{} listed {} in its deps, but it is a proc-macro. It should instead be in the bazel property proc_macro_deps.".format( - ctx.label, - dep.label, - ), - ) - for dep in ctx.attr.proc_macro_deps: - type = dep[rust_common.crate_info].type - if type != "proc-macro": - fail( - "{} listed {} in its proc_macro_deps, but it is not proc-macro, it is a {}. It should probably instead be listed in deps.".format( - ctx.label, - dep.label, - type, - ), - ) def _rust_library_impl(ctx): """The implementation of the `rust_library` rule. @@ -148,7 +124,7 @@ def _rust_library_common(ctx, crate_type): list: A list of providers. See `rustc_compile_action` """ _assert_no_deprecated_attributes(ctx) - _assert_correct_dep_mapping(ctx) + deps, proc_macro_deps = partition_deps(ctx) toolchain = find_toolchain(ctx) @@ -195,8 +171,8 @@ def _rust_library_common(ctx, crate_type): not ctx.attr.disable_pipelining ) - deps = transform_deps(ctx.attr.deps) - proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx)) + deps = transform_deps(deps) + proc_macro_deps = transform_deps(proc_macro_deps + get_import_macro_deps(ctx)) return rustc_compile_action( ctx = ctx, @@ -238,7 +214,7 @@ def _rust_binary_impl(ctx): """ toolchain = find_toolchain(ctx) crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name) - _assert_correct_dep_mapping(ctx) + deps, proc_macro_deps = partition_deps(ctx) if ctx.attr.binary_name: output_filename = ctx.attr.binary_name @@ -246,8 +222,8 @@ def _rust_binary_impl(ctx): output_filename = ctx.label.name output = ctx.actions.declare_file(output_filename + toolchain.binary_ext) - deps = transform_deps(ctx.attr.deps) - proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx)) + deps = transform_deps(deps) + proc_macro_deps = transform_deps(proc_macro_deps + get_import_macro_deps(ctx)) crate_root = getattr(ctx.file, "crate_root", None) if not crate_root: @@ -327,13 +303,13 @@ def _rust_test_impl(ctx): list: The list of providers. See `rustc_compile_action` """ _assert_no_deprecated_attributes(ctx) - _assert_correct_dep_mapping(ctx) + deps, proc_macro_deps = partition_deps(ctx) toolchain = find_toolchain(ctx) crate_type = "bin" - deps = transform_deps(ctx.attr.deps) - proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx)) + deps = transform_deps(deps) + proc_macro_deps = transform_deps(proc_macro_deps + get_import_macro_deps(ctx)) if ctx.attr.crate and ctx.attr.srcs: fail("rust_test.crate and rust_test.srcs are mutually exclusive. Update {} to use only one of these attributes".format( @@ -1072,6 +1048,21 @@ rust_shared_library = rule( """), ) +def _exec_transition_impl(_settings, attr): + return { + "//command_line_option:is exec configuration": not attr.internal_doctest_transition_override, + "//command_line_option:stamp": False, + } + +_exec_transition = transition( + inputs = [], + outputs = [ + "//command_line_option:is exec configuration", + "//command_line_option:stamp", + ], + implementation = _exec_transition_impl, +) + def _proc_macro_dep_transition_impl(settings, _attr): if settings["//rust/private:is_proc_macro_dep_enabled"]: return {"//rust/private:is_proc_macro_dep": True} @@ -1105,7 +1096,11 @@ rust_proc_macro = rule( """), cfg = _proc_macro_dep_transition, ), + internal_doctest_transition_override = attr.bool( + doc = "Used for internal testing; do not set", + ), ), + cfg = _exec_transition, fragments = ["cpp"], toolchains = [ str(Label("//rust:toolchain_type")), diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 60d5cfc6a0..3fbaf6f088 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -229,7 +229,7 @@ def collect_deps( Args: deps (list): The deps from ctx.attr.deps. - proc_macro_deps (list): The proc_macro deps from ctx.attr.proc_macro_deps. + proc_macro_deps (list): The proc_macro_deps from partition_deps(ctx). aliases (dict): A dict mapping aliased targets to their actual Crate information. Returns: diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 36afda488d..8be08d3d7d 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -18,7 +18,7 @@ load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("//rust/private:common.bzl", "rust_common") load("//rust/private:providers.bzl", "CrateInfo") load("//rust/private:rustdoc.bzl", "rustdoc_compile_action") -load("//rust/private:utils.bzl", "dedent", "find_toolchain", "transform_deps") +load("//rust/private:utils.bzl", "dedent", "find_toolchain", "partition_deps", "transform_deps") def _construct_writer_arguments(ctx, test_runner, opt_test_params, action, crate_info): """Construct arguments and environment variables specific to `rustdoc_test_writer`. @@ -110,8 +110,9 @@ def _rust_doc_test_impl(ctx): toolchain = find_toolchain(ctx) crate = ctx.attr.crate[rust_common.crate_info] - deps = transform_deps(ctx.attr.deps) - proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps) + deps, proc_macro_deps = partition_deps(ctx) + deps = transform_deps(deps) + proc_macro_deps = transform_deps(proc_macro_deps) crate_info = rust_common.create_crate_info( name = crate.name, diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl index df0ad4a980..5b3e959644 100644 --- a/rust/private/utils.bzl +++ b/rust/private/utils.bzl @@ -498,6 +498,28 @@ def is_exec_configuration(ctx): # TODO(djmarcin): Is there any better way to determine cfg=exec? return ctx.genfiles_dir.path.find("-exec") != -1 +def partition_deps(ctx): + """Split deps into normal deps and proc_macro_deps. + + Args: + ctx (ctx): The current rule's context object + + Returns: + deps, proc_macro_deps + """ + if ctx.attr.proc_macro_deps: + print("`proc_macro_deps` attribute is deprecated; all deps can go in `deps`") + + deps = [] + proc_macro_deps = [] + for dep in ctx.attr.deps + ctx.attr.proc_macro_deps: + if CrateInfo in dep and dep[CrateInfo].type == "proc-macro": + proc_macro_deps.append(dep) + else: + deps.append(dep) + + return deps, proc_macro_deps + def transform_deps(deps): """Transforms a [Target] into [DepVariantInfo]. diff --git a/test/unit/is_proc_macro_dep/is_proc_macro_dep_test.bzl b/test/unit/is_proc_macro_dep/is_proc_macro_dep_test.bzl index 26e2dcd7a1..ba5b583a21 100644 --- a/test/unit/is_proc_macro_dep/is_proc_macro_dep_test.bzl +++ b/test/unit/is_proc_macro_dep/is_proc_macro_dep_test.bzl @@ -65,7 +65,7 @@ is_proc_macro_dep_is_not_in_env_for_top_level_action_test = analysistest.make(_i def _is_proc_macro_dep_is_false_for_proc_macro(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) - proc_macro_dep_action = [a for a in tut[DepActionsInfo].actions if str(a) == "action 'Compiling Rust proc-macro proc_macro_crate (1 files)'"][0] + proc_macro_dep_action = [a for a in tut[DepActionsInfo].actions if str(a) == "action 'Compiling Rust proc-macro proc_macro_crate (1 files) [for tool]'"][0] asserts.equals(env, proc_macro_dep_action.env["BAZEL_RULES_RUST_IS_PROC_MACRO_DEP"], "0") return analysistest.end(env) @@ -83,7 +83,7 @@ is_proc_macro_dep_is_false_for_top_level_library_test = analysistest.make(_is_pr def _is_proc_macro_dep_is_true_for_proc_macro_dep(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) - proc_macro_dep_action = [a for a in tut[DepActionsInfo].actions if str(a) == "action 'Compiling Rust rlib proc_macro_dep (1 files)'"][0] + proc_macro_dep_action = [a for a in tut[DepActionsInfo].actions if str(a) == "action 'Compiling Rust rlib proc_macro_dep (1 files) [for tool]'"][0] asserts.equals(env, proc_macro_dep_action.env["BAZEL_RULES_RUST_IS_PROC_MACRO_DEP"], "1") return analysistest.end(env) diff --git a/test/unit/rustdoc/rustdoc_unit_test.bzl b/test/unit/rustdoc/rustdoc_unit_test.bzl index aa1f9b2f02..df7e63b9f1 100644 --- a/test/unit/rustdoc/rustdoc_unit_test.bzl +++ b/test/unit/rustdoc/rustdoc_unit_test.bzl @@ -190,8 +190,7 @@ def _target_maker(rule_fn, name, rustdoc_deps = [], rustdoc_proc_macro_deps = [] rust_doc_test( name = "{}_doctest".format(name), crate = ":{}".format(name), - deps = rustdoc_deps, - proc_macro_deps = rustdoc_proc_macro_deps, + deps = rustdoc_deps + rustdoc_proc_macro_deps, target_compatible_with = NOT_WINDOWS, ) @@ -241,6 +240,7 @@ def _define_targets(): rust_proc_macro, name = "rustdoc_proc_macro", srcs = ["rustdoc_proc_macro.rs"], + internal_doctest_transition_override = True, ) _target_maker(