-
-
Notifications
You must be signed in to change notification settings - Fork 775
refactor(allocator/vec): clarify comment #11071
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
refactor(allocator/vec): clarify comment #11071
Conversation
CodSpeed Instrumentation Performance ReportMerging #11071 will not alter performanceComparing Summary
|
Dunqing
left a comment
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.
Thank you! I understand a little bit how to write a caller guarantee related safety comment
|
I don't know if this helps, but the way I conceptualize it is: Unsafe functions have a "contract". They require the caller to ensure the terms of the contract are always upheld. In return, the unsafe function promises that UB can't happen, if the caller keeps their side of the bargain. Like a real-world legal contract, both sides (the function and its caller) need to understand the terms of the contract, and agree to them. When the caller calls the function in an The safety comments represent the contract and the signing of it.
In addition: Both safe and unsafe functions can provide guarantees, which should also be documented. e.g. When code calls an unsafe function, it can list the guarantees other functions provided as "evidence" that it's impossible it will ever break the safety contract. Note: What makes a function unsafe is not that it includes unsafe code. What makes it an unsafe function is that it requires the caller to sign a contract. Here's a silly example: pub struct FourBytes {
bytes: [u8; 4],
/// Current index.
/// SAFETY: Must always be less than 4.
current_index: usize,
}
impl FourBytes {
pub fn new() -> Self {
// SAFETY: `current_index: 0` satisfies safety constraint
// of the type that `current_index < 4`.
Self { bytes: [11, 22, 33, 44], current_index: 0 }
}
/// Set current index, without bounds checks.
///
/// # SAFETY
/// `index` must be less than 4.
unsafe fn set_current_index_unchecked(&mut self, index: usize) {
self.current_index = index;
}
/// Get the current byte.
fn get_current(&self) -> u8 {
// SAFETY: `new` and `set_current_index_unchecked`
// are the only methods which set `current_index`.
// Both ensure `current_index` is never greater than 4,
// so reading `self.bytes[self.current_index]` cannot be out of bounds.
unsafe {
*self.bytes.get_unchecked(self.current_index)
}
}
}
|
Merge activity
|
Follow-on after #10884. Clarify comment as to why `as u32` is valid here.
c0bd73a to
fc2f040
Compare
I finally found time to review your comment. It's very helpful, for sure! Your explanation and example are very easy to understand! I am looking forward to writing more quite safe "unsafe code" 😂 |

Follow-on after #10884. Clarify comment as to why
as u32is valid here.