5959//! The `#[global_allocator]` can only be used once in a crate
6060//! or its recursive dependencies.
6161
62+ #![ deny( unsafe_op_in_unsafe_fn) ]
6263#![ stable( feature = "alloc_module" , since = "1.28.0" ) ]
6364
6465use core:: intrinsics;
@@ -158,7 +159,9 @@ unsafe impl AllocRef for System {
158159 #[ inline]
159160 unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
160161 if layout. size ( ) != 0 {
161- GlobalAlloc :: dealloc ( self , ptr. as_ptr ( ) , layout)
162+ // SAFETY: The safety guarantees are explained in the documentation
163+ // for the `GlobalAlloc` trait and its `dealloc` method.
164+ unsafe { GlobalAlloc :: dealloc ( self , ptr. as_ptr ( ) , layout) }
162165 }
163166 }
164167
@@ -184,16 +187,36 @@ unsafe impl AllocRef for System {
184187 match placement {
185188 ReallocPlacement :: InPlace => Err ( AllocErr ) ,
186189 ReallocPlacement :: MayMove if layout. size ( ) == 0 => {
187- let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
190+ let new_layout =
191+ // SAFETY: The new size and layout alignement guarantees
192+ // are transfered to the caller (they come from parameters).
193+ //
194+ // See the preconditions for `Layout::from_size_align` to
195+ // see what must be checked.
196+ unsafe { Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) } ;
188197 self . alloc ( new_layout, init)
189198 }
190199 ReallocPlacement :: MayMove => {
191- // `realloc` probably checks for `new_size > size` or something similar.
192- intrinsics:: assume ( new_size > size) ;
193- let ptr = GlobalAlloc :: realloc ( self , ptr. as_ptr ( ) , layout, new_size) ;
194- let memory =
195- MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } ;
196- init. init_offset ( memory, size) ;
200+ // SAFETY:
201+ //
202+ // The safety guarantees are explained in the documentation
203+ // for the `GlobalAlloc` trait and its `dealloc` method.
204+ //
205+ // `realloc` probably checks for `new_size > size` or something
206+ // similar.
207+ //
208+ // For the guarantees about `init_offset`, see its documentation:
209+ // `ptr` is assumed valid (and checked for non-NUL) and
210+ // `memory.size` is set to `new_size` so the offset being `size`
211+ // is valid.
212+ let memory = unsafe {
213+ intrinsics:: assume ( new_size > size) ;
214+ let ptr = GlobalAlloc :: realloc ( self , ptr. as_ptr ( ) , layout, new_size) ;
215+ let memory =
216+ MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } ;
217+ init. init_offset ( memory, size) ;
218+ memory
219+ } ;
197220 Ok ( memory)
198221 }
199222 }
@@ -220,14 +243,28 @@ unsafe impl AllocRef for System {
220243 match placement {
221244 ReallocPlacement :: InPlace => Err ( AllocErr ) ,
222245 ReallocPlacement :: MayMove if new_size == 0 => {
223- self . dealloc ( ptr, layout) ;
246+ // SAFETY: see `GlobalAlloc::dealloc` for the guarantees that
247+ // must be respected. `ptr` and `layout` are parameters and so
248+ // those guarantees must be checked by the caller.
249+ unsafe { self . dealloc ( ptr, layout) } ;
224250 Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
225251 }
226252 ReallocPlacement :: MayMove => {
227- // `realloc` probably checks for `new_size < size` or something similar.
228- intrinsics:: assume ( new_size < size) ;
229- let ptr = GlobalAlloc :: realloc ( self , ptr. as_ptr ( ) , layout, new_size) ;
230- Ok ( MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size } )
253+ // SAFETY:
254+ //
255+ // See `GlobalAlloc::realloc` for more informations about the
256+ // guarantees expected by this method. `ptr`, `layout` and
257+ // `new_size` are parameters and the responsability for their
258+ // correctness is left to the caller.
259+ //
260+ // `realloc` probably checks for `new_size < size` or something
261+ // similar.
262+ let memory = unsafe {
263+ intrinsics:: assume ( new_size < size) ;
264+ let ptr = GlobalAlloc :: realloc ( self , ptr. as_ptr ( ) , layout, new_size) ;
265+ MemoryBlock { ptr : NonNull :: new ( ptr) . ok_or ( AllocErr ) ?, size : new_size }
266+ } ;
267+ Ok ( memory)
231268 }
232269 }
233270 }
@@ -300,13 +337,19 @@ pub mod __default_lib_allocator {
300337
301338 #[ rustc_std_internal_symbol]
302339 pub unsafe extern "C" fn __rdl_alloc ( size : usize , align : usize ) -> * mut u8 {
303- let layout = Layout :: from_size_align_unchecked ( size, align) ;
304- System . alloc ( layout)
340+ // SAFETY: see the guarantees expected by `Layout::from_size_align` and
341+ // `GlobalAlloc::alloc`.
342+ unsafe {
343+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
344+ System . alloc ( layout)
345+ }
305346 }
306347
307348 #[ rustc_std_internal_symbol]
308349 pub unsafe extern "C" fn __rdl_dealloc ( ptr : * mut u8 , size : usize , align : usize ) {
309- System . dealloc ( ptr, Layout :: from_size_align_unchecked ( size, align) )
350+ // SAFETY: see the guarantees expected by `Layout::from_size_align` and
351+ // `GlobalAlloc::dealloc`.
352+ unsafe { System . dealloc ( ptr, Layout :: from_size_align_unchecked ( size, align) ) }
310353 }
311354
312355 #[ rustc_std_internal_symbol]
@@ -316,13 +359,21 @@ pub mod __default_lib_allocator {
316359 align : usize ,
317360 new_size : usize ,
318361 ) -> * mut u8 {
319- let old_layout = Layout :: from_size_align_unchecked ( old_size, align) ;
320- System . realloc ( ptr, old_layout, new_size)
362+ // SAFETY: see the guarantees expected by `Layout::from_size_align` and
363+ // `GlobalAlloc::realloc`.
364+ unsafe {
365+ let old_layout = Layout :: from_size_align_unchecked ( old_size, align) ;
366+ System . realloc ( ptr, old_layout, new_size)
367+ }
321368 }
322369
323370 #[ rustc_std_internal_symbol]
324371 pub unsafe extern "C" fn __rdl_alloc_zeroed ( size : usize , align : usize ) -> * mut u8 {
325- let layout = Layout :: from_size_align_unchecked ( size, align) ;
326- System . alloc_zeroed ( layout)
372+ // SAFETY: see the guarantees expected by `Layout::from_size_align` and
373+ // `GlobalAlloc::alloc_zeroed`.
374+ unsafe {
375+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
376+ System . alloc_zeroed ( layout)
377+ }
327378 }
328379}
0 commit comments