-
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
Document unsafety in src/libcore/slice/mod.rs
#73555
Document unsafety in src/libcore/slice/mod.rs
#73555
Conversation
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
1930b7a
to
bcd9688
Compare
☔ The latest upstream changes (presumably #73643) made this pull request unmergeable. Please resolve the merge conflicts. |
bcd9688
to
a4095ca
Compare
Rebased to resolve the conflicts. |
// SAFETY: the condition of the `while` guarantees that | ||
// `i` and `ln - i - chunk` are inside the slice. | ||
// The resulting pointers `pa` and `pb` are therefore valid, | ||
// and can be read from and written to. |
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.
These comments also need to touch on the larger-pieced bytes being still in-bounds based on the indexing. Personally I would like to see some short proof-y wording, maybe something like this.
Personally I feel like just saying "well the condition guarantees things" doesn't help much since it doesn't allow for modifying or understanding why this is the case.
An unaligned u32 can be read from i if i + 1 < ln (and obviously i < ln),
because each element is 2 bytes and we're reading 4.
i + chunk - 1 < ln / 2 # while condition
i + 2 - 1 < ln / 2
i + 1 < ln / 2
Since it's less than the length divided by 2, then it must be in bounds.
@@ -1548,14 +1571,14 @@ impl<T> [T] { | |||
while size > 1 { | |||
let half = size / 2; | |||
let mid = base + half; | |||
// mid is always in [0, size), that means mid is >= 0 and < size. | |||
// SAFETY: mid is always in [0, size), that means mid is >= 0 and < size. |
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.
// SAFETY: mid is always in [0, size), that means mid is >= 0 and < size. | |
// SAFETY: |
Obviously pre-existing but this is not really saying anything and the next two lines are precisely what we need
@@ -2013,6 +2036,13 @@ impl<T> [T] { | |||
let mut next_read: usize = 1; | |||
let mut next_write: usize = 1; | |||
|
|||
// SAFETY: the `while` condition guarantees `next_read` and `next_write` | |||
// are less than `len`, thus are inside `self`. `prev_ptr_write` points to |
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.
We should make a note that next_write is incremented at most once per loop somewhere in here.
// `prev_ptr_write` is never less than 0 and is inside the slice. | ||
// This fulfils the requirements for dereferencing `ptr_read`, `prev_ptr_write` | ||
// and `ptr_write`, and for using `ptr.add(next_read)`, `ptr.add(next_write - 1)` | ||
// and `prev_ptr_write.offset(1)`. |
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.
FWIW some of these constructions seem pretty strange, I wouldn't want to edit the code in this PR but ptr.add(next_write - 1)
seems like it should be next_write.sub(1)
.
@@ -2300,6 +2334,9 @@ impl<T> [T] { | |||
T: Copy, | |||
{ | |||
assert_eq!(self.len(), src.len(), "destination and source slices have different lengths"); | |||
// SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was |
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.
// SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was | |
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was |
@@ -2300,6 +2334,9 @@ impl<T> [T] { | |||
T: Copy, | |||
{ | |||
assert_eq!(self.len(), src.len(), "destination and source slices have different lengths"); | |||
// SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was | |||
// checked to have the same length. Both slices cannot be overlapping because |
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.
// checked to have the same length. Both slices cannot be overlapping because | |
// checked to have the same length. The slices cannot overlap because |
@@ -2300,6 +2334,9 @@ impl<T> [T] { | |||
T: Copy, | |||
{ | |||
assert_eq!(self.len(), src.len(), "destination and source slices have different lengths"); | |||
// SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was | |||
// checked to have the same length. Both slices cannot be overlapping because | |||
// Rust's mutable references are exclusive. |
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.
// Rust's mutable references are exclusive. | |
// mutable references are exclusive. |
☔ The latest upstream changes (presumably #74330) made this pull request unmergeable. Please resolve the merge conflicts. |
Closing this after a discussion with the author since they don't have time to commit to this and it is small enough that can be redone later or someone could pick it up if needed. Thanks |
…e-slice, r=LukasKalbertodt Document unsafety in library/core/src/slice/mod.rs Restart where rust-lang#73555 left off, helping with rust-lang#66219.
Helps with #66219.
r? @Mark-Simulacrum