Skip to content

Commit e6b72df

Browse files
jswrennjoshlf
andauthored
Apply suggestions from code review
Co-authored-by: Joshua Liebow-Feeser <[email protected]>
1 parent cf0a160 commit e6b72df

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

src/next_array.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,28 @@ impl<T, const N: usize> ArrayBuilder<T, N> {
3838
// invariant of `self.arr`. Even if this line panics, we have not
3939
// created any intermediate invalid state.
4040
*place = MaybeUninit::new(value);
41-
// PANICS: This cannot panic, since `self.len < N <= usize::MAX`.
42-
// `0..self.len` are valid. Due to the above write, the element at
43-
// `self.len` is now also valid. Consequently, all elements at indicies
44-
// `0..(self.len + 1)` are valid, and `self.len` can be safely
45-
// incremented without violating `self.arr`'s invariant. It is fine if
46-
// this increment panics, as we have not created any intermediate
47-
// invalid state.
41+
// Lemma: `self.len < N`. By invariant, `self.len <= N`. Above, we index
42+
// into `self.arr`, which has size `N`, at index `self.len`. If `self.len == N`
43+
// at that point, that index would be out-of-bounds, and the index
44+
// operation would panic. Thus, `self.len != N`, and since `self.len <= N`,
45+
// that means that `self.len < N`.
46+
//
47+
// PANICS: Since `self.len < N`, and since `N <= usize::MAX`,
48+
// `self.len + 1 <= usize::MAX`, and so `self.len += 1` will not
49+
// overflow. Overflow is the only panic condition of `+=`.
50+
//
51+
// SAFETY:
52+
// - We are required to uphold the invariant that `self.len <= N`.
53+
// Since, by the preceding lemma, `self.len < N` at this point in the
54+
// code, `self.len += 1` results in `self.len <= N`.
55+
// - We are required to uphold the invariant that `self.arr[..self.len]`
56+
// are valid instances of `T`. Since this invariant already held when
57+
// this method was called, and since we only increment `self.len`
58+
// by 1 here, we only need to prove that the element at
59+
// `self.arr[self.len]` (using the value of `self.len` before incrementing)
60+
// is valid. Above, we construct `place` to point to `self.arr[self.len]`,
61+
// and then initialize `*place` to `MaybeUninit::new(value)`, which is
62+
// a valid `T` by construction.
4863
self.len += 1;
4964
}
5065

@@ -92,7 +107,7 @@ impl<T, const N: usize> Drop for ArrayBuilder<T, N> {
92107
// selectively run their destructors.
93108
fn drop(&mut self) {
94109
// SAFETY:
95-
// - by invariant on `&[T]`, `self.as_mut()` is:
110+
// - by invariant on `&mut [T]`, `self.as_mut()` is:
96111
// - valid for reads and writes
97112
// - properly aligned
98113
// - non-null

0 commit comments

Comments
 (0)