Add test directive needs-target-has-atomic#133095
Add test directive needs-target-has-atomic#133095kei519 wants to merge 2 commits intorust-lang:masterfrom
needs-target-has-atomic#133095Conversation
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @compiler-errors (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
|
Some changes occurred in src/tools/compiletest cc @jieyouxu |
|
Also, is there a typo in the description? I would assume it's |
|
No. My code accepts both |
|
I'll leave more feedback tmrw, but pls only accept the colon version |
|
Fixed it. |
jieyouxu
left a comment
There was a problem hiding this comment.
Thanks for the PR!
We should call this directive //@ needs-target-has-atomic to match the cfg(target_has_atomic) and accept the same values, and we should not accept comments on this directive or have any kind of otherwise fancy parsing because they become a footgun in actual usage.
I left some feedback about issues with the target-has-atomic target-specific info detection and the directive parsing itself. Also we should introduce a new self-test and we should not be modifying that other rustc cli ui test which explicitly is trying to ban setting the builtin cfg by the user.
There was a problem hiding this comment.
Problem: this test must not be modified, this is a compiler ui test checking rustc forbids the user setting a builtin-cfg via cli.
There was a problem hiding this comment.
Instead, this can be a new tests/ui/compiletest-self-test/only-target-has-atomic that cherry-picks a well-known tier 1 arch / target like x86_64-unknown-gnu-linux that is very unlikely to change its target_has_atomic values.
There was a problem hiding this comment.
I misunderstood.
However jyn514 says
you have to specify the platforms and architectures you want by hand
on #87377, but aren't there any tests codes including has-atomic constraint written by hand?
There was a problem hiding this comment.
Yes, but also no. You can always do the #[cfg(target_has_atomic = "ptr")] by hand, however, that is not known to compiletest (compiletest only looks at //@ directives), so if you do that you can't communicate to compiletest if the test is actually ignored instead of vacuously passed (because #[cfg(blah)] panic!() won't trigger unless there's a blah revision).
There was a problem hiding this comment.
Problem: we should keep //@ needs-target-has-atomic matching the #[cfg(target_has_atomic)] semantics otherwise it adds needless confusion. In particular, this directive should support (cf. https://doc.rust-lang.org/reference/conditional-compilation.html#target_has_atomic):
//@ needs-target-has-atomic: 8
//@ needs-target-has-atomic: 16
//@ needs-target-has-atomic: 32
//@ needs-target-has-atomic: 64
//@ needs-target-has-atomic: 128
//@ needs-target-has-atomic: ptr
Possibly comma-separated so the test-writer can combine them, e.g.
//@ target-has-atomic: 8, 16, 32, 64, 128, ptr
There was a problem hiding this comment.
Shouldn't we accept (none), i.e. below
//@ needs-target-has-atomiclike the cfg equivalent?
#[cfg(target_has_atomic)]There was a problem hiding this comment.
No. Apparently target_has_atomic = "8" is not quite target_has_atomic; the latter is a nightly-only unstable cfg. For the purposes of these tests, I think we are only interested in the target_has_atomic="value" builtin cfgs. We can always slightly adjust this logic in a follow-up if needed.
| // Because `needs-atomic` accepts one argument after colon to specify data size, we check whther | ||
| // comment starts with colon. | ||
| let (name, comment, comment_starts_with_colon) = if let Some(index) = ln.find([':', ' ']) { | ||
| (&ln[..index], Some(&ln[index + 1..]), ln.as_bytes()[index] == b':') | ||
| } else { | ||
| (ln, None, false) |
There was a problem hiding this comment.
Problem: let's not accept comments on this directive because it makes the parsing very complicated. If needed, the test writer can just use a regular comment on a previous/following line.
src/tools/compiletest/src/common.rs
Outdated
| pub fn has_atomic(&self, size: Option<u64>) -> bool { | ||
| if let Some(size) = size { | ||
| (self.target_cfg().min_atomic_width()..=self.target_cfg().max_atomic_width()) | ||
| .contains(&size) | ||
| && self.target_cfg().atomic_cas | ||
| } else { | ||
| self.target_cfg().atomic_cas | ||
| } | ||
| } |
There was a problem hiding this comment.
Problem [DETECTION 2/2]: ditto.
|
@rustbot author |
needs-atomicneeds-target-has-atomic
|
And I added a new test, but I'm not sure whether the test is enough. @rustbot review |
jieyouxu
left a comment
There was a problem hiding this comment.
Thanks, I have a few more nits, but this looks good!
| pub fn has_atomic(&self, size: &str) -> bool { | ||
| for config in | ||
| rustc_output(self, &["--print=cfg", "--target", &self.target], Default::default()) | ||
| .trim() | ||
| .lines() | ||
| { | ||
| let Some((key, value)) = config.split_once("=\"").map(|(k, v)| { | ||
| (k, v.strip_suffix('"').expect("key-value pair should be properly quoted")) | ||
| }) else { | ||
| continue; | ||
| }; | ||
| if key == "target_has_atomic" && value == size { | ||
| return true; | ||
| } | ||
| } | ||
| false | ||
| } |
There was a problem hiding this comment.
Remark (for myself): I should review how we are handling rustc --print outputs.
There was a problem hiding this comment.
Suggestion: actually, can this just use a regex (lazily/once initialized ofc)? Like
static TARGET_HAS_ATOMIC: LazyLock<Regex> =
LazyLock::new(||
Regex::new(r"target_has_atomic=\"(?<width>[0-9A-Za-z]+)\"").unwrap()
);| let (name, comment, comment_starts_with_colon) = if let Some(index) = ln.find([':', ' ']) { | ||
| (&ln[..index], Some(&ln[index + 1..]), ln.as_bytes()[index] == b':') | ||
| } else { | ||
| (ln, None, false) | ||
| }; |
There was a problem hiding this comment.
Suggestion: this also accepts a whitespace separator, please only accept : to help consistency.
There was a problem hiding this comment.
This accepts a whitespace separator, but only when the directive isn't needs-target-has-atomic. See here.
It should accept a whitespace separator when other than needs-target-has-atomic because it is currently accepted. Shouldn't it?
| // `needs-target-has-atomic` requires comma-separated data sizes. | ||
| if !comment_starts_with_colon || comment.is_none() { | ||
| return IgnoreDecision::Error { | ||
| message: "`needs-target-has-atomic` requires data sizes for atomic operations" | ||
| .into(), | ||
| }; | ||
| } | ||
| let comment = comment.unwrap(); | ||
|
|
||
| // Parse the comment to specify data sizes. | ||
| for size in comment.split(',').map(|size| size.trim()) { | ||
| if !["ptr", "128", "64", "32", "16", "8"].contains(&size) { | ||
| return IgnoreDecision::Error { | ||
| message: "expected values for `needs-target-has-atomic` are: `128`, `16`, \ | ||
| `32`, `64`, `8`, and `ptr`" | ||
| .into(), | ||
| }; | ||
| } | ||
| if !config.has_atomic(size) { | ||
| return IgnoreDecision::Ignore { | ||
| reason: if size == "ptr" { | ||
| "ignored on targets without ptr-size atomic operations".into() | ||
| } else { | ||
| format!("ignored on targets without {size}-bit atomic operations") | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
| return IgnoreDecision::Continue; |
There was a problem hiding this comment.
Suggestion: this is non-trivial, so can you extract this into a helper?
| // Check this ignored because x86_64-unknown-linux-gnu does not have 128-bit atomic operation. | ||
|
|
||
| //@ only-x86_64-unknown-linux-gnu | ||
| //@ needs-target-has-atomic: 128 |
There was a problem hiding this comment.
Suggestion: this could get invalidated in the future because the target might get 128-bit atomic operations in the future, but it's fine in the meantime.
Can you make this instead a headers/tests.rs test? E.g.
|
Fixed excpet
|
|
Thanks for the PR, I found it easier to reimplement than to review (because the compiletest setup here was quite convoluted and subtle), so I adapted your changes into a new PR #133736 (co-authored by you, of course) and I rolled another reviewer. |
…r=compiler-errors Add `needs-target-has-atomic` directive Before this PR, the test writer has to specify platforms and architectures by hand for targets that have differing atomic width support. `#[cfg(target_has_atomic="...")]` is not quite the same because (1) you may have to specify additional matchers manually which has to be maintained individually, and (2) the `#[cfg]` blocks does not communicate to compiletest that a test would be ignored for a given target. This PR implements a `//@ needs-target-has-atomic` directive which admits a comma-separated list of required atomic widths that the target must satisfy in order for the test to run. ``` //@ needs-target-has-atomic: 8, 16, ptr ``` See <rust-lang#87377>. This PR supersedes rust-lang#133095 and is co-authored by `@kei519,` because it was somewhat subtle, and it turned out easier to implement than to review. rustc-dev-guide docs PR: rust-lang/rustc-dev-guide#2154
Rollup merge of rust-lang#133736 - jieyouxu:needs-target-has-atomic, r=compiler-errors Add `needs-target-has-atomic` directive Before this PR, the test writer has to specify platforms and architectures by hand for targets that have differing atomic width support. `#[cfg(target_has_atomic="...")]` is not quite the same because (1) you may have to specify additional matchers manually which has to be maintained individually, and (2) the `#[cfg]` blocks does not communicate to compiletest that a test would be ignored for a given target. This PR implements a `//@ needs-target-has-atomic` directive which admits a comma-separated list of required atomic widths that the target must satisfy in order for the test to run. ``` //@ needs-target-has-atomic: 8, 16, ptr ``` See <rust-lang#87377>. This PR supersedes rust-lang#133095 and is co-authored by `@kei519,` because it was somewhat subtle, and it turned out easier to implement than to review. rustc-dev-guide docs PR: rust-lang/rustc-dev-guide#2154
Add
needs-atomictest directive to reduce specifying architectures that have atomic operations in test (fix #87377).This directive requires comma separated operation sizes: