-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add test directive needs-target-has-atomic
#133095
Conversation
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
tests/ui/cfg/disallowed-cli-cfgs.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we accept (none), i.e. below
//@ needs-target-has-atomic
like the cfg equivalent?
#[cfg(target_has_atomic)]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem [DETECTION 2/2]: ditto.
@rustbot author |
needs-atomic
needs-target-has-atomic
And I added a new test, but I'm not sure whether the test is enough. @rustbot review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have a few more nits, but this looks good!
src/tools/compiletest/src/common.rs
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remark (for myself): I should review how we are handling rustc --print
outputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: this also accepts a whitespace separator, please only accept :
to help consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll double-check tmrw
// `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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
fn threads_support() { |
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-atomic
test directive to reduce specifying architectures that have atomic operations in test (fix #87377).This directive requires comma separated operation sizes: