-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
BTreeMap: tougher checking on most uses of copy_nonoverlapping #80391
Conversation
Includes #80390. I only just noticed that many slice functions like |
I don't think order matters too much, but we can switch to using copy_nonoverlapping_to which is defined directly on raw pointers, which seems much better to me than thinking about order of arguments :) Ideally I think we'd seek to do the same for the slice functions, and we might look at putting them on MaybeUninit itself. |
ptr::copy_nonoverlapping(source.as_ptr(), dest.as_mut_ptr(), source.len()); | ||
} | ||
if cfg!(debug_assertions) { | ||
// Tell Miri that the copied slice became uninitialized, and zero it in debug builds. |
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.
What do you mean by zero it in debug builds? This isn't zeroing anything...
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.
Probably not contractually, but in practice it zeroes, both in builds of alloc and in this playground example.
@RalfJung I am interested in hearing your thoughts on a move and move_nonoverlapping function on ptr or MaybeUninit - it seems kind of odd to have it hand-rolled in terms of the de-initializing and such in btree code (indeed I would rather reject this PR as-is; I think we should not hand roll primitives in the btree code - it's sufficiently complicated without needing to know new functions behavior). |
08913b5
to
172ba9d
Compare
This baffles me. Do you wish Naturally I wish there were standard ways for working with variable length arrays of |
I mean moving them to standard library APIs, they are of course useful as methods and I wouldn't just inline them. |
@@ -1739,9 +1725,35 @@ unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T { | |||
let slice_ptr = slice.as_mut_ptr(); | |||
let ret = (*slice_ptr.add(idx)).assume_init_read(); | |||
ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); | |||
if cfg!(debug_assertions) { | |||
// Tell Miri about the trailing element, and zero it in debug builds. |
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.
What does it mean to "tell Miri" about an element?
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.
As in the description, that it became uninitialized.
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.
Ah I see... that wasn't clear (also because it's in the hidden part of the diff).
This is a weird operation... it's not really useful aside from making Miri complain about future uses of this memory (assuming those uses actually do things that are illegal for uninit memory, such as arithmetic/logic operations). Or am I missing something? |
I'm not sure you're talking about |
I guess I considered it to work on a level below the one where "copy" vs "move" is a meaningful distinction. I view this as being mostly a type-system-level fiction; on the level of unsafe code messing around with the underlying bytes, they are both the same. In particular, note that the exact behavior of "MIR-level
Fair. I guess what I meant to say is -- there is no precedent for APIs that express such "Miri-only effects". |
Yes, that's another way of putting it: ptr::copy_nonoverlapping is too low level for arrays of Once you have that, there is some meaningful distinction between "move" and "copy". But what What's left is the
Isn't MaybeUninit::uninit a "debug build and Miri-only effect"? |
172ba9d
to
4004a81
Compare
No, that function is called in many situations where people don't care about Miri at all. |
5ac3db4
to
77eb289
Compare
77eb289
to
1ed9cb8
Compare
modulo rename r=me |
1ed9cb8
to
26b9462
Compare
@bors r+ |
📌 Commit 26b9462 has been approved by |
☀️ Test successful - checks-actions |
Miri checks pointer provenance and destination, but we can check it in debug builds already.
Also, we can let Miri confirm we don't mistake imprints of moved keys and values as genuine.
r? @Mark-Simulacrum