@@ -172,8 +172,22 @@ impl<T> TypedArena<T> {
172172 available_bytes >= additional_bytes
173173 }
174174
175+ /// Allocates storage for `len >= 1` values in this arena, and returns a
176+ /// raw pointer to the first value's storage.
177+ ///
178+ /// # Safety
179+ ///
180+ /// Caller must initialize each of the `len` slots to a droppable value
181+ /// before the arena is dropped.
182+ ///
183+ /// In practice, this typically means that the caller must be able to
184+ /// raw-copy `len` already-initialized values into the slice without any
185+ /// possibility of panicking.
186+ ///
187+ /// FIXME(Zalathar): This is *very* fragile; perhaps we need a different
188+ /// approach to arena-allocating slices of droppable values.
175189 #[ inline]
176- fn alloc_raw_slice ( & self , len : usize ) -> * mut T {
190+ unsafe fn alloc_raw_slice ( & self , len : usize ) -> * mut T {
177191 assert ! ( size_of:: <T >( ) != 0 ) ;
178192 assert ! ( len != 0 ) ;
179193
@@ -208,7 +222,7 @@ impl<T> TypedArena<T> {
208222 & self ,
209223 iter : impl IntoIterator < Item = Result < T , E > > ,
210224 ) -> Result < & mut [ T ] , E > {
211- // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason
225+ // Despite the similarity with `DroplessArena`, we cannot reuse their fast case. The reason
212226 // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a
213227 // reference to `self` and adding elements to the arena during iteration.
214228 //
@@ -229,9 +243,15 @@ impl<T> TypedArena<T> {
229243 }
230244 // Move the content to the arena by copying and then forgetting it.
231245 let len = vec. len ( ) ;
232- let start_ptr = self . alloc_raw_slice ( len) ;
246+
247+ // SAFETY: After allocating raw storage for exactly `len` values, we
248+ // must fully initialize the storage without panicking, and we must
249+ // also prevent the stale values in the vec from being dropped.
233250 Ok ( unsafe {
251+ let start_ptr = self . alloc_raw_slice ( len) ;
252+ // Initialize the newly-allocated storage without panicking.
234253 vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
254+ // Prevent the stale values in the vec from being dropped.
235255 vec. set_len ( 0 ) ;
236256 slice:: from_raw_parts_mut ( start_ptr, len)
237257 } )
@@ -584,7 +604,7 @@ impl DroplessArena {
584604 & self ,
585605 iter : impl IntoIterator < Item = Result < T , E > > ,
586606 ) -> Result < & mut [ T ] , E > {
587- // Despite the similarlty with `alloc_from_iter`, we cannot reuse their fast case, as we
607+ // Despite the similarity with `alloc_from_iter`, we cannot reuse their fast case, as we
588608 // cannot know the minimum length of the iterator in this case.
589609 assert ! ( size_of:: <T >( ) != 0 ) ;
590610
0 commit comments