-
Couldn't load subscription status.
- Fork 13.9k
Add overflow_checks intrinsic
#128666
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
base: master
Are you sure you want to change the base?
Add overflow_checks intrinsic
#128666
Conversation
|
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt This PR changes Stable MIR cc @oli-obk, @celinval, @ouz-a Some changes occurred in src/tools/clippy cc @rust-lang/clippy Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 |
|
Given how invasive and boilerplatey the implementation of the intrinsic is, I strongly prefer we not merge this unless it comes with well-motivated use in the standard library implementation. |
|
Just to be clear, do you mean the existing motivation (better debug behavior for |
|
Oh wow that wording I left was very unclear. I'll try to explain myself better this time. The implementation strategy that is currently used for the runtime UB checks (intrinsic which lowers to a new NullOp that's branched on) is concerningly heavy on both compiler implementation complexity and compile-time overhead. There are 4 places where the runtime UB checks are cfg'd out or not merged yet because their compile-time overhead isn't justifiable ( Before we merge the compiler complexity in this PR, I want evidence that actually using the new intrinsic for its intended purpose has tolerable compile-time overhead. If the compile-time overhead of the approach in this PR is so high that its use must be avoided in often-instantiated code paths, we should find another strategy. So what would make me happy is a draft PR based on this one (or just modifying this PR) that swaps in the new range types and uses this new I've mostly put up with the UB checks implementation because I have finite time to investigate things, and it has so far been a mostly-successful way to deliver a feature we've been missing for years. My leading theory on a better way to do this is to have a magic |
|
☔ The latest upstream changes (presumably #128707) made this pull request unmergeable. Please resolve the merge conflicts. |
|
It's worth noting that like the UB checks flag, if this gets added we need to ensure that ctfe always runs with either the flag enabled or disabled and is not affected by any kind of rustc flag as otherwise it would be unsound for const generics (#129552). I think what @saethlin said about making sure this is actually usable in practice is a good point so marked this as S-blocked until that is resolved. |
|
I'm wondering if these cases where we want to enable extra checks in the standard library should be fixed by improving and stabilizing the cargo option to build the standard library together with the target crate. |
|
I too would love to see all of the issues addressed: https://github.com/rust-lang/wg-cargo-std-aware/issues?q=is%3Aissue+label%3A%22stabilization+blocker%22+is%3Aopen but it's a huge engineering and political effort. If you'd like to push forward such work, a PR is not the right place to advocate for it. |
I'm just trying to understand the motivation behind the chosen approach, which I think is a fair point to ask. What are the trade-offs and why this has to be solved by adding more logic to the compiler backend so the std library behaves like any other cargo dependency. From what I understand, building the standard library in cargo is out of the table given its current state. So thank you for clarifying. |
|
I'm gonna close this since it's not had any activity for ~2 months and making progress seems somewhat blocked. Feel free to re-open this at some future point. |
803f841 to
a7c9eb6
Compare
|
Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr Some changes occurred in compiler/rustc_codegen_ssa Some changes occurred to the CTFE machinery The Miri subtree was changed cc @rust-lang/miri Some changes occurred to constck cc @fee1-dead |
|
Reopening this because I noticed the recent addition of the Running perf on this PR should give us some idea of how much impact this kind of check would have on compile times if the new |
This comment has been minimized.
This comment has been minimized.
FYI, I'm contemplating removing |
|
☔ The latest upstream changes (presumably #141700) made this pull request unmergeable. Please resolve the merge conflicts. |
a7c9eb6 to
fa8b3be
Compare
This comment has been minimized.
This comment has been minimized.
|
I've rebased this on latest master, and moved the perf-testing commit to #146288 |
This comment has been minimized.
This comment has been minimized.
|
☔ The latest upstream changes (presumably #146683) made this pull request unmergeable. Please resolve the merge conflicts. |
80e7831 to
74cccf7
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This has so far been done with the rust/library/core/src/iter/range.rs Lines 237 to 241 in 6a9f223
If we have two mechanisms that do almost the same thing like this, we should also have clear guidance somewhere on which one to use when. |
|
@RalfJung maybe my explanation wasn't great. The use case this supports is not something that can be achieved with just that attribute. That implementation is actually included in this PR in case you didn't see it, see commit 74cccf7 It's not just a conditional panic, it's the extra work of not panicking when the overflow would normally happen, deferring that panic to the subsequent call. (Maybe it's possible another way but I haven't been able to work it out, and I've tried a lot) |
#146288 adds additional code, gated by this new intrinsic, to the Can we consider the matter resolved? |
|
Yes, I think you've demonstrated that there is a fair chance this does not have significant compile-time overhead. |
|
Perfect! Thanks for the quick response. @rustbot ready |
|
☔ The latest upstream changes (presumably #147782) made this pull request unmergeable. Please resolve the merge conflicts. |
library/core/src/intrinsics/mod.rs
Outdated
| } | ||
| /// Returns whether we should perform some overflow-checking at runtime. This eventually evaluates to | ||
| /// `cfg!(overflow_checks)`, but behaves different from `cfg!` when mixing crates built with different | ||
| /// flags: if the crate has UB checks enabled or carries the `#[rustc_preserve_overflow_checks]` |
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.
you say UB checks a bunch here, it should be overflow checks instead right?
library/core/src/intrinsics/mod.rs
Outdated
| /// a crate that does not delay evaluation further); otherwise it can happen any time. | ||
| /// | ||
| /// The common case here is a user program built with overflow_checks linked against the distributed | ||
| /// sysroot which is built without overflow_checks but with `#[rustc_preserve_overflow_checks]`. |
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.
| /// sysroot which is built without overflow_checks but with `#[rustc_preserve_overflow_checks]`. | |
| /// sysroot which is built without overflow_checks but with `#[rustc_inherit_overflow_checks]`. |
judging by ur tests
| ) -> InterpResult<$tcx, bool> { | ||
| // We can't look at `tcx.sess` here as that can differ across crates, which can lead to | ||
| // unsound differences in evaluating the same constant at different instantiation sites. | ||
| interp_ok(true) |
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 means that overflow checks using the intrinsic will always be run by ctfe, even when debug assertions and overflow checks are disabled. can you add a test for this?
| #[unstable(feature = "new_range_api", issue = "125687")] | ||
| #[derive(Debug, Clone)] | ||
| pub struct IterRangeFrom<A>(legacy::RangeFrom<A>); | ||
| pub struct IterRangeFrom<A> { |
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.
compiler impl looks reasonable to me. If you split out the libs changes to a separate PR I can approve this myself, otherwise needs libs approval too. I'm not sure where tests for libs stuff is supposed to go, I'm not certain that it's tests/ui but I honestly couldn't tell you
|
sorry for taking a while to get to this. needs a rebase too |
check overflow after yielding MAX value `0_u8..` will yield `255` and only panic on the subsequent `next()`
74cccf7 to
7547dd5
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This adds an intrinsic which allows code in a pre-built library to inherit the overflow checks option from a crate depending on it. This enables code in the standard library to explicitly change behavior based on whether
overflow_checksare enabled, regardless of the setting used when standard library was compiled.This is very similar to the
ub_checksintrinsic, and refactors the two to use a common mechanism.The primary use case for this is to allow the new
RangeFromiterator to yield the maximum element before overflowing, as requested here. This PR includes a workingIterRangeFromimplementation based on this new intrinsic that exhibits the desired behavior.Prior discussion on Zulip