Problem
Found a couple of bad interactions with proc macro tests around runner config in Cargo.
The current stable and nightly behavior looks pretty inconsistent.
Proc-macro are host artifacts.
Cargo also appears to treat them that way when compiling them.
cargo test --lib --target <target> does not pass --target to rustc
for the proc-macro crate itself.
However,
the test executable produced for a proc-macro crate sometimes uses target.runner / target.'cfg(…)'.runner.
That makes proc-macro tests special in a way that is hard to explain:
they are compiled as host artifacts, but can be run with a target runner.
The behavior also changes depending on -Ztarget-applies-to-host and -Zhost-config.
Downstream tools such as Miri need to know whether a proc-macro test will be run directly or through a runner.
This kind of inconsistency make their lives miserable.
The behavior captured around #17198 is:
| Case |
Current behavior |
proc-macro test, no --target, [target.<host>].runner |
runner applies |
proc-macro test, no --target, [target.'cfg(all())'].runner |
runner applies |
proc-macro test, --target <host>, [target.<host>].runner |
runner applies |
proc-macro test, --target <host>, [target.'cfg(all())'].runner |
runner applies |
proc-macro test, -Ztarget-applies-to-host -Zhost-config --target <host>, [target.<host>].runner |
target runner applies |
proc-macro test, -Ztarget-applies-to-host -Zhost-config --target <host>, [target.'cfg(all())'].runner |
cfg runner applies |
proc-macro test, -Ztarget-applies-to-host -Zhost-config --target <host>, [host].runner only |
no runner applies |
proc-macro test, -Ztarget-applies-to-host -Zhost-config --target <alternate>, [host], [target.<host>], and [target.'cfg(all())'] runners |
no runner applies |
The last two rows are especially weird.
If proc-macro tests are host artifacts,
then [host].runner not applying is surprising.
If the historical model is that proc-macro test executables use target runners,
then the cross-target -Zhost-config case not using any configured runner is also surprising.
Steps
The behavior can be reproduced with a proc-macro package that has a unit test.
The tests added in #17198 capture the current behavior:
custom_runner_proc_macro_test
custom_runner_cfg_proc_macro_test
custom_runner_proc_macro_test_with_target
custom_runner_cfg_proc_macro_test_with_target
custom_runner_proc_macro_test_with_host_config
custom_runner_cfg_proc_macro_test_with_host_config
custom_runner_cfg_proc_macro_test_with_host_config_no_target
host_runner_proc_macro_test
custom_runner_proc_macro_test_with_cross_target
custom_runner_proc_macro_test_with_cross_target_host_config
Possible Solution(s)
From @RalfJung in #17198 (comment):
What is the intended behavior of target.runner wrt proc macro tests in various flag configurations after this PR?
- IMO it should never apply since proc macro tests clearly are a host artifact. Even cargo agrees with that: cargo passes
--target to rustc for target artifacts, but does not pass --target to proc macro tests. So IMO with this PR cargo becomes internally inconsistent, where proc macro tests are the only kinds of crates that get built without --target but they get run with target.runner. That's why Miri needs special hacks to work around this inconsistency.
- I could live with it always applying
target.runner. We'll just have to keep our special hack in Miri then.
- But if it gets sometimes applied and sometimes not (depending on
-Z flags or so), then Miri is screwed. (Well maybe there's something complicated we can do depending on the exact circumstances of what this looks like. But it sure won't be pretty.)9[
Notes
This came up while working on #17198.
That PR intentionally restores stable behavior that changed after #17123.
It is not meant to settle this behavior permanently.
Related discussion:
Version
cargo 1.97.0 (c980f4866 2026-06-30)
cargo 1.98.0-beta.1 (f40cc7a13 2026-07-01)
- 0a28f79
Problem
Found a couple of bad interactions with proc macro tests around runner config in Cargo.
The current stable and nightly behavior looks pretty inconsistent.
Proc-macro are host artifacts.
Cargo also appears to treat them that way when compiling them.
cargo test --lib --target <target>does not pass--targettorustcfor the proc-macro crate itself.
However,
the test executable produced for a proc-macro crate sometimes uses
target.runner/target.'cfg(…)'.runner.That makes proc-macro tests special in a way that is hard to explain:
they are compiled as host artifacts, but can be run with a target runner.
The behavior also changes depending on
-Ztarget-applies-to-hostand-Zhost-config.Downstream tools such as Miri need to know whether a proc-macro test will be run directly or through a runner.
This kind of inconsistency make their lives miserable.
The behavior captured around #17198 is:
--target,[target.<host>].runner--target,[target.'cfg(all())'].runner--target <host>,[target.<host>].runner--target <host>,[target.'cfg(all())'].runner-Ztarget-applies-to-host -Zhost-config --target <host>,[target.<host>].runner-Ztarget-applies-to-host -Zhost-config --target <host>,[target.'cfg(all())'].runner-Ztarget-applies-to-host -Zhost-config --target <host>,[host].runneronly-Ztarget-applies-to-host -Zhost-config --target <alternate>,[host],[target.<host>], and[target.'cfg(all())']runnersThe last two rows are especially weird.
If proc-macro tests are host artifacts,
then
[host].runnernot applying is surprising.If the historical model is that proc-macro test executables use target runners,
then the cross-target
-Zhost-configcase not using any configured runner is also surprising.Steps
The behavior can be reproduced with a proc-macro package that has a unit test.
The tests added in #17198 capture the current behavior:
custom_runner_proc_macro_testcustom_runner_cfg_proc_macro_testcustom_runner_proc_macro_test_with_targetcustom_runner_cfg_proc_macro_test_with_targetcustom_runner_proc_macro_test_with_host_configcustom_runner_cfg_proc_macro_test_with_host_configcustom_runner_cfg_proc_macro_test_with_host_config_no_targethost_runner_proc_macro_testcustom_runner_proc_macro_test_with_cross_targetcustom_runner_proc_macro_test_with_cross_target_host_configPossible Solution(s)
From @RalfJung in #17198 (comment):
What is the intended behavior of
target.runnerwrt proc macro tests in various flag configurations after this PR?--targetto rustc for target artifacts, but does not pass--targetto proc macro tests. So IMO with this PR cargo becomes internally inconsistent, where proc macro tests are the only kinds of crates that get built without--targetbut they get run withtarget.runner. That's why Miri needs special hacks to work around this inconsistency.target.runner. We'll just have to keep our special hack in Miri then.-Zflags or so), then Miri is screwed. (Well maybe there's something complicated we can do depending on the exact circumstances of what this looks like. But it sure won't be pretty.)9[Notes
This came up while working on #17198.
That PR intentionally restores stable behavior that changed after #17123.
It is not meant to settle this behavior permanently.
Related discussion:
-Zhost-configbreakscargo miri teston proc macros under Miri miri#5101Version
cargo 1.97.0 (c980f4866 2026-06-30)cargo 1.98.0-beta.1 (f40cc7a13 2026-07-01)