-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
mem::swap behaves incorrectly in CTFE (and Miri) #94371
Comments
Cc @rust-lang/wg-const-eval |
Playground miri is on 2-12, so I don't have an easy way to check, but something like this should hit it: #[repr(C)]
struct Demo(u64, u32, u64, u32, u64, u32, u64);
fn main() {
let mut x = Demo(1, 2, 3, 4, 5, 6, 7);
let mut y = Demo(10, 11, 12, 13, 14, 15, 16);
std::mem::swap(&mut x, &mut y);
} To get to the code in question, the type needs:
Basically, it needs to be a type that's big enough to bother, but isn't something special (like an AVX2 vector). Aside: That error output is beautiful! |
🙈 lots of fun things that can go wrong here. These are not easy to fix, but maybe we can buy us some time by just using |
You mean
Thanks, we spent a lot of work on it. :) |
This comment was marked as resolved.
This comment was marked as resolved.
Ah, got it: #![feature(const_swap)]
#![feature(const_mut_refs)]
#[repr(C)]
struct Demo(u64, bool, u64, u32, u64, u64, u64);
const C: (Demo, Demo) = {
let mut x = Demo(1, true, 3, 4, 5, 6, 7);
let mut y = Demo(10, false, 12, 13, 14, 15, 16);
std::mem::swap(&mut x, &mut y);
(x, y)
}; Looks like my mistake was looking at |
Interesting that it's asymmetric. The only asymmetry that exists in the implementation (that I can remember, at least) is rust/library/core/src/mem/mod.rs Lines 743 to 745 in d981633
So does the fact that only one of them errored mean that this might be "fixed" (probably not for the unaligned pointer case) if that was changed from (Though it's probably still better to not use the over-complicated code in CTFE/Miri anyway.) |
Yes. |
#94411 indeed fixes the testcase (but the PR still needs more work) |
…oli-obk For MIRI, cfg out the swap vectorization logic from 94212 Because of rust-lang#69488 the swap logic from rust-lang#94212 doesn't currently work in MIRI. Copying in smaller pieces is probably much worse for its performance anyway, so it'd probably rather just use the simple path regardless. Part of rust-lang#94371, though another PR will be needed for the CTFE aspect. r? `@oli-obk` cc `@RalfJung`
…i-obk For MIRI, cfg out the swap vectorization logic from 94212 Because of rust-lang#69488 the swap logic from rust-lang#94212 doesn't currently work in MIRI. Copying in smaller pieces is probably much worse for its performance anyway, so it'd probably rather just use the simple path regardless. Part of rust-lang#94371, though another PR will be needed for the CTFE aspect. r? `@oli-obk` cc `@RalfJung`
With #94527 landed, we might want to revert #94412?
but OTOH, it would be valuable to test the actual code path that is used in real code, so without conclusive benchmarks I would default to removing the |
Oh never mind, Miri would still break on copying data with pointers at 'odd' offsets inside it due to #87184. |
Since #94212,
mem::swap
behaves incorrectly during CTFE (where it is unstably accessible) and in Miri. This is demonstrated by the following code failing to build:The error is:
The underlying reason for this is #69488: the new
swap
copies the data in chunks ofMaybeUninit<usize>
, but this is implemented incorrectly in CTFE and Miri in the sense that if any of the bytes in the source of such a value is uninit, then the entire value becomes uninit after the copy.This reproduces only with very particular types that hit certain code paths in
swap
; my attempts at writing a smaller example from scratch failed so instead I extracted this from the test harness where the problem originally occurred in Miri.Also, even a fix #69488 would not fully resolve the problem: if data contains pointers at unaligned positions, then the
usize
chunking might attempt to copy a part of a pointer, which CTFE and Miri do not support (that's #87184, and it is a lot harder to fix than #69488). This was in theory already a problem with the previous implementation ofswap
, but there the chunks were bigger so pointers were less likely to cross the chunk boundary. I don't know if this is ever a problem in practice though. Miri/CTFE will halt when such a partial pointer copy is attempted, so we should know if/when that happens.The text was updated successfully, but these errors were encountered: