Skip to content

Commit 8cc87a0

Browse files
committed
Add safety documentation
1 parent 7ef262e commit 8cc87a0

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

packages/std/src/memory.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,17 @@ const _: () = {
3737

3838
impl Region<Borrowed> {
3939
pub fn from_slice(slice: &[u8]) -> Self {
40+
// SAFETY: A slice upholds all the safety variants we need to construct a borrowed Region
4041
unsafe { Self::from_parts(slice.as_ptr(), slice.len(), slice.len()) }
4142
}
4243
}
4344

4445
impl Region<Owned> {
4546
/// Construct a region from an existing vector
4647
pub fn from_vec(vec: Vec<u8>) -> Self {
48+
// SAFETY: The `std::vec::Vec` type upholds all the safety invariants required to call `from_parts`
4749
let region = unsafe { Self::from_parts(vec.as_ptr(), vec.capacity(), vec.len()) };
50+
// Important and load bearing: call `mem::forget` to prevent memory from being freed
4851
mem::forget(vec);
4952
region
5053
}
@@ -72,6 +75,7 @@ impl Region<Owned> {
7275

7376
/// Transform the region into a vector
7477
pub fn into_vec(self) -> Vec<u8> {
78+
// SAFETY: Invariants are covered by the safety contract of the constructor
7579
let vector = unsafe {
7680
Vec::from_raw_parts(
7781
self.offset as *mut u8,
@@ -88,6 +92,14 @@ impl<O> Region<O>
8892
where
8993
O: Ownership,
9094
{
95+
/// # Safety
96+
///
97+
/// This function requires the following invariants to be upheld:
98+
/// - `capacity` is smaller or equal to `length`
99+
/// - The number of bytes allocated by the pointer must be equal to `capacity`
100+
/// - The byte range covered by `length` must be initialized
101+
/// - `ptr` is a non-dangling and non-null pointer
102+
/// - If the generic `Ownership` parameter is set to `Owned`, the `ptr` must point to a memory region allocated by a `Vec`
91103
unsafe fn from_parts(ptr: *const u8, capacity: usize, length: usize) -> Self {
92104
// Well, this technically violates pointer provenance rules.
93105
// But there isn't a stable API for it, so that's the best we can do, I guess.
@@ -102,6 +114,7 @@ where
102114

103115
/// Access the memory region this region points to in form of a byte slice
104116
pub fn as_bytes(&self) -> &[u8] {
117+
// SAFETY: Safety contract of constructor requires `length` bytes to be initialized
105118
unsafe { slice::from_raw_parts(self.offset as *const u8, self.length as usize) }
106119
}
107120

@@ -146,6 +159,8 @@ where
146159
// "The pointer will never be null, so this type is null-pointer-optimized."
147160
assert!(!region_start.is_null(), "Region starts at null pointer");
148161

162+
// SAFETY: Since `from_parts` was required to uphold the invariance that if the parameter is `Owned`
163+
// the memory has been allocated through a `Vec`, we can safely reconstruct the `Vec` and deallocate it.
149164
unsafe {
150165
let data =
151166
Vec::from_raw_parts(region_start, self.length as usize, self.capacity as usize);

0 commit comments

Comments
 (0)