@@ -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