@@ -38,13 +38,28 @@ impl<T, const N: usize> ArrayBuilder<T, N> {
38
38
// invariant of `self.arr`. Even if this line panics, we have not
39
39
// created any intermediate invalid state.
40
40
* 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.
48
63
self . len += 1 ;
49
64
}
50
65
@@ -92,7 +107,7 @@ impl<T, const N: usize> Drop for ArrayBuilder<T, N> {
92
107
// selectively run their destructors.
93
108
fn drop ( & mut self ) {
94
109
// SAFETY:
95
- // - by invariant on `&[T]`, `self.as_mut()` is:
110
+ // - by invariant on `&mut [T]`, `self.as_mut()` is:
96
111
// - valid for reads and writes
97
112
// - properly aligned
98
113
// - non-null
0 commit comments