Skip to main content

memapi2/traits/
alloc_mut.rs

1use {
2    crate::{
3        error::Error,
4        layout::Layout,
5        traits::{
6            AllocError,
7            alloc::{Alloc, Dealloc, Grow, Realloc, Shrink},
8            helpers::{
9                Bytes,
10                alloc_mut::{grow_mut, ralloc_mut, shrink_unchecked_mut},
11                default_dealloc_panic
12            }
13        }
14    },
15    ::core::{
16        cmp::{Ord, Ordering},
17        convert::From,
18        marker::Sized,
19        ptr::{self, NonNull},
20        result::Result::{self, Err, Ok}
21    }
22};
23
24/// A memory allocation interface which may require mutable access to itself to perform operations.
25///
26/// All types which are [`Alloc`] are also [`AllocMut`], making this more generic than [`Alloc`].
27pub trait AllocMut: AllocError {
28    /// Attempts to allocate a block of memory fitting the given [`Layout`].
29    ///
30    /// # Errors
31    ///
32    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
33    ///
34    /// The standard implementations may return:
35    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
36    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
37    ///   feature is enabled, it will be
38    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
39    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
40    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[layout.size()](Layout::size) ==
41    ///   0</code>.
42    ///
43    /// [last_os_error]: ::std::io::Error::last_os_error
44    /// [raw_os_error]: ::std::io::Error::raw_os_error
45    fn alloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <Self as AllocError>::Error>;
46
47    /// Attempts to allocate a zeroed block of memory fitting the given [`Layout`].
48    ///
49    /// # Errors
50    ///
51    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
52    ///
53    /// The standard implementations may return:
54    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
55    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
56    ///   feature is enabled, it will be
57    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
58    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
59    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[layout.size()](Layout::size) ==
60    ///   0</code>.
61    ///
62    /// [last_os_error]: ::std::io::Error::last_os_error
63    /// [raw_os_error]: ::std::io::Error::raw_os_error
64    #[cfg_attr(miri, track_caller)]
65    #[inline]
66    fn zalloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
67        zalloc!(self, alloc_mut, layout)
68    }
69}
70
71/// A memory allocation interface which may require mutable access to itself and can also deallocate
72/// memory.
73///
74/// All types which are [`Dealloc`] are also [`DeallocMut`], making this more generic than
75/// [`Dealloc`].
76pub trait DeallocMut: AllocMut {
77    /// Deallocates a previously allocated block.
78    ///
79    /// This is a noop if <code>[layout.size()](Layout::size) == 0</code> or `ptr` is
80    /// [`dangling`](ptr::dangling).
81    ///
82    /// The default implementation simply calls [`try_dealloc_mut`](DeallocMut::try_dealloc_mut) and
83    /// panics if it returns an error.
84    ///
85    /// # Safety
86    ///
87    /// The caller must ensure:
88    /// - `ptr` points to a block of memory allocated using this allocator.
89    /// - `layout` describes exactly the same block.
90    ///
91    /// # Panics
92    ///
93    /// This function may panic if the [`try_dealloc_mut`](DeallocMut::try_dealloc_mut)
94    /// implementation returns an error, or the implementation chooses to panic for any other
95    /// reason. It will not panic if `ptr` is [`dangling`](ptr::dangling) or
96    /// <code>[layout.size()](Layout::size) == 0</code>.
97    #[track_caller]
98    #[inline]
99    unsafe fn dealloc_mut(&mut self, ptr: NonNull<u8>, layout: Layout) {
100        default_dealloc!(self.try_dealloc_mut, ptr, layout);
101    }
102
103    /// Attempts to deallocate a previously allocated block. If this allocator is backed by an
104    /// allocation library which does not provide fallible deallocation operations, this may panic,
105    /// abort, or incorrectly return `Ok(())`.
106    ///
107    /// # Safety
108    ///
109    /// The caller must ensure:
110    /// - `ptr` points to a block of memory allocated using this allocator.
111    /// - `layout` describes exactly the same block.
112    ///
113    /// # Errors
114    ///
115    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
116    ///
117    /// The standard implementations may return:
118    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[layout.size()](Layout::size) ==
119    ///   0</code>.
120    /// - <code>Err([Error::DanglingDeallocation])</code> if <code>ptr ==
121    ///   [layout.dangling](Layout::dangling)</code>.
122    /// - <code>Err([Error::Unsupported]))</code> if deallocation is unsupported. In this case,
123    ///   reallocation via [`Grow`], [`Shrink`], and [`Realloc`] may still be supported.
124    unsafe fn try_dealloc_mut(
125        &mut self,
126        ptr: NonNull<u8>,
127        layout: Layout
128    ) -> Result<(), <Self as AllocError>::Error>;
129
130    /// Attempts to deallocate a previously allocated block after performing validity checks.
131    ///
132    /// This method must return an error rather than silently accepting the deallocation and
133    /// potentially causing UB.
134    ///
135    /// # Errors
136    ///
137    /// Implementations commonly return:
138    /// - <code>Err([Error::ZeroSizedLayout])</code> if `layout.size() == 0`.
139    /// - <code>Err([Error::DanglingDeallocation])</code> if `ptr == layout.dangling()`.
140    /// - <code>Err([Error::Unsupported])</code> if checked deallocation is unsupported.
141    /// - <code>Err([Error::Other]\(err\))</code> for allocator-specific validation failures.
142    fn checked_dealloc_mut(
143        &mut self,
144        _ptr: NonNull<u8>,
145        _layout: Layout
146    ) -> Result<(), <Self as AllocError>::Error> {
147        Err(<Self as AllocError>::Error::from(Error::Unsupported))
148    }
149}
150
151/// A memory allocation interface which may require mutable access to itself and can also grow
152/// allocations.
153///
154/// All types which are [`Grow`] are also [`GrowMut`], making this more generic than [`Grow`].
155pub trait GrowMut: AllocMut + DeallocMut {
156    /// Grows the given block to a new, larger layout.
157    ///
158    /// On failure, the original memory will not be deallocated.
159    ///
160    /// Note that the default implementation simply:
161    /// 1. Checks that the new layout is larger or the same size. If both layouts are the same,
162    ///    `ptr` is returned and no operation is performed.
163    /// 2. Allocates a new block of memory via [`AllocMut::alloc_mut`].
164    /// 3. Copies [`old_layout.size()`](Layout::size) bytes from the old block to the new block.
165    /// 4. Deallocates the old block.
166    /// 5. Returns a pointer to the new block.
167    ///
168    /// # Safety
169    ///
170    /// The caller must ensure:
171    /// - `ptr` points to a block of memory allocated using this allocator.
172    /// - `old_layout` describes exactly the same block.
173    ///
174    /// # Errors
175    ///
176    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
177    ///
178    /// The standard implementations may return:
179    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
180    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
181    ///   feature is enabled, it will be
182    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
183    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
184    /// - <code>Err([Error::GrowSmallerNewLayout]\([old_layout.size()](Layout::size),
185    ///   [new_layout.size()](Layout::size))\)</code> if <code>[old_layout.size()](Layout::size) >
186    ///   [new_layout.size()](Layout::size)</code>.
187    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[new_layout.size()](Layout::size) ==
188    ///   0</code>.
189    ///
190    /// [last_os_error]: ::std::io::Error::last_os_error
191    /// [raw_os_error]: ::std::io::Error::raw_os_error
192    #[cfg_attr(miri, track_caller)]
193    #[inline]
194    unsafe fn grow_mut(
195        &mut self,
196        ptr: NonNull<u8>,
197        old_layout: Layout,
198        new_layout: Layout
199    ) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
200        grow_mut(self, ptr, old_layout, new_layout, Bytes::Uninitialized)
201    }
202
203    /// Grows the given block to a new, larger layout, with extra bytes being zeroed.
204    ///
205    /// On failure, the original memory will not be deallocated.
206    ///
207    /// Note that the default implementation simply:
208    /// 1. Checks that the new layout is larger or the same size. If both layouts are the same,
209    ///    `ptr` is returned and no operation is performed.
210    /// 2. Allocates a new block of memory via [`AllocMut::zalloc_mut`].
211    /// 3. Copies [`old_layout.size()`](Layout::size) bytes from the old block to the new block.
212    /// 4. Deallocates the old block.
213    /// 5. Returns a pointer to the new block.
214    ///
215    /// # Safety
216    ///
217    /// The caller must ensure:
218    /// - `ptr` points to a block of memory allocated using this allocator.
219    /// - `old_layout` describes exactly the same block.
220    ///
221    /// # Errors
222    ///
223    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
224    ///
225    /// The standard implementations may return:
226    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
227    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
228    ///   feature is enabled, it will be
229    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
230    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
231    /// - <code>Err([Error::GrowSmallerNewLayout]\([old_layout.size()](Layout::size),
232    ///   [new_layout.size()](Layout::size))\)</code> if <code>[old_layout.size()](Layout::size) >
233    ///   [new_layout.size()](Layout::size)</code>.
234    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[new_layout.size()](Layout::size) ==
235    ///   0</code>.
236    ///
237    /// [last_os_error]: ::std::io::Error::last_os_error
238    /// [raw_os_error]: ::std::io::Error::raw_os_error
239    #[cfg_attr(miri, track_caller)]
240    #[inline]
241    unsafe fn zgrow_mut(
242        &mut self,
243        ptr: NonNull<u8>,
244        old_layout: Layout,
245        new_layout: Layout
246    ) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
247        grow_mut(self, ptr, old_layout, new_layout, Bytes::Zeroed)
248    }
249}
250
251/// A memory allocation interface which may require mutable access to itself and can also shrink
252/// allocations.
253///
254/// All types which are [`Shrink`] are also [`ShrinkMut`], making this more generic than [`Shrink`].
255pub trait ShrinkMut: AllocMut + DeallocMut {
256    /// Shrinks the given block to a new, smaller layout.
257    ///
258    /// On failure, the original memory will not be deallocated.
259    ///
260    /// Note that the default implementation simply:
261    /// 1. Checks that the new layout is smaller or the same size. If both layouts are the same,
262    ///    `ptr` is returned and no operation is performed.
263    /// 2. Allocates a new block of memory via [`AllocMut::alloc_mut`].
264    /// 3. Copies [`new_layout.size()`](Layout::size) bytes from the old block to the new block.
265    ///    This will discard any extra bytes from the old block.
266    /// 4. Deallocates the old block.
267    /// 5. Returns a pointer to the new block.
268    ///
269    /// # Safety
270    ///
271    /// The caller must ensure:
272    /// - `ptr` points to a block of memory allocated using this allocator.
273    /// - `old_layout` describes exactly the same block.
274    ///
275    /// # Errors
276    ///
277    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
278    ///
279    /// The standard implementations may return:
280    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
281    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
282    ///   feature is enabled, it will be
283    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
284    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
285    /// - <code>Err([Error::ShrinkLargerNewLayout]\([old_layout.size()](Layout::size),
286    ///   [new_layout.size()](Layout::size))\)</code> if <code>[old_layout.size()](Layout::size) <
287    ///   [new_layout.size()](Layout::size)</code>.
288    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[new_layout.size()](Layout::size) ==
289    ///   0</code>.
290    ///
291    /// [last_os_error]: ::std::io::Error::last_os_error
292    /// [raw_os_error]: ::std::io::Error::raw_os_error
293    #[cfg_attr(miri, track_caller)]
294    unsafe fn shrink_mut(
295        &mut self,
296        ptr: NonNull<u8>,
297        old_layout: Layout,
298        new_layout: Layout
299    ) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
300        default_shrink!(self::shrink_unchecked_mut, ptr, old_layout, new_layout)
301    }
302}
303
304/// A memory allocation interface which may require mutable access to itself and can arbitrarily
305/// resize allocations.
306///
307/// All types which are [`Realloc`] are also [`ReallocMut`], making this more generic than
308/// [`Realloc`].
309pub trait ReallocMut: GrowMut + ShrinkMut {
310    /// Reallocates a block, growing or shrinking as needed.
311    ///
312    /// On grow, preserves existing contents up to [`old_layout.size()`](Layout::size), and on
313    /// shrink, truncates to [`new_layout.size()`](Layout::size).
314    ///
315    /// On failure, the original memory will not be deallocated.
316    ///
317    /// # Safety
318    ///
319    /// The caller must ensure:
320    /// - `ptr` points to a block previously allocated with this allocator.
321    /// - `old_layout` describes exactly the same block.
322    ///
323    /// # Errors
324    ///
325    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
326    ///
327    /// The standard implementations may return:
328    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
329    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
330    ///   feature is enabled, it will be
331    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
332    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
333    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[new_layout.size()](Layout::size) ==
334    ///   0</code>.
335    ///
336    /// [last_os_error]: ::std::io::Error::last_os_error
337    /// [raw_os_error]: ::std::io::Error::raw_os_error
338    #[cfg_attr(miri, track_caller)]
339    #[inline]
340    unsafe fn realloc_mut(
341        &mut self,
342        ptr: NonNull<u8>,
343        old_layout: Layout,
344        new_layout: Layout
345    ) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
346        ralloc_mut(self, ptr, old_layout, new_layout, Bytes::Uninitialized)
347    }
348
349    /// Reallocates a block, growing or shrinking as needed, with extra bytes being zeroed.
350    ///
351    /// On grow, preserves existing contents up to [`old_layout.size()`](Layout::size), and on
352    /// shrink, truncates to [`new_layout.size()`](Layout::size).
353    ///
354    /// On failure, the original memory will not be deallocated.
355    ///
356    /// # Safety
357    ///
358    /// The caller must ensure:
359    /// - `ptr` points to a block previously allocated with this allocator.
360    /// - `old_layout` describes exactly the same block.
361    ///
362    /// # Errors
363    ///
364    /// Errors are implementation-defined, refer to [`AllocError::Error`] and [`Error`].
365    ///
366    /// The standard implementations may return:
367    /// - <code>Err([Error::AllocFailed]\(layout, cause\))</code> if allocation fails. `cause` is
368    ///   typically [`Cause::Unknown`](crate::error::Cause::Unknown). If the `os_err_reporting`
369    ///   feature is enabled, it will be
370    ///   <code>[Cause::OSErr](crate::error::Cause::OSErr)(oserr)</code>. In this case, `oserr` will
371    ///   be the error from <code>[last_os_error]\(\).[raw_os_error]\(\)</code>.
372    /// - <code>Err([Error::ZeroSizedLayout])</code> if <code>[new_layout.size()](Layout::size) ==
373    ///   0</code>.
374    ///
375    /// [last_os_error]: ::std::io::Error::last_os_error
376    /// [raw_os_error]: ::std::io::Error::raw_os_error
377    #[cfg_attr(miri, track_caller)]
378    #[inline]
379    unsafe fn rezalloc_mut(
380        &mut self,
381        ptr: NonNull<u8>,
382        old_layout: Layout,
383        new_layout: Layout
384    ) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
385        ralloc_mut(self, ptr, old_layout, new_layout, Bytes::Zeroed)
386    }
387}
388
389/// A memory allocation interface which may require mutable access and can allocate and deallocate.
390///
391/// This exists solely because it reads more nicely than <code>A: [DeallocMut]</code>; the two are
392/// the same.
393pub trait BasicAllocMut: AllocMut + DeallocMut {}
394/// A memory allocation interface which may require mutable access and can allocate, deallocate,
395/// and arbitrarily resize allocations.
396///
397/// This exists solely because it reads more nicely than <code>A: [ReallocMut]</code>; the two are
398/// the same.
399pub trait FullAllocMut: ReallocMut + GrowMut + ShrinkMut + AllocMut + DeallocMut {}
400
401impl<A: AllocMut + DeallocMut> BasicAllocMut for A {}
402impl<A: ReallocMut + GrowMut + ShrinkMut + AllocMut + DeallocMut> FullAllocMut for A {}
403
404impl<A: Alloc + ?Sized> AllocMut for A {
405    #[cfg_attr(miri, track_caller)]
406    #[inline(always)]
407    fn alloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <A as AllocError>::Error> {
408        (*self).alloc(layout)
409    }
410
411    #[cfg_attr(miri, track_caller)]
412    #[inline(always)]
413    fn zalloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <A as AllocError>::Error> {
414        (*self).zalloc(layout)
415    }
416}
417
418impl<A: Dealloc + ?Sized> DeallocMut for A {
419    #[cfg_attr(miri, track_caller)]
420    #[inline(always)]
421    unsafe fn dealloc_mut(&mut self, ptr: NonNull<u8>, layout: Layout) {
422        (*self).dealloc(ptr, layout);
423    }
424
425    #[cfg_attr(miri, track_caller)]
426    #[inline(always)]
427    unsafe fn try_dealloc_mut(
428        &mut self,
429        ptr: NonNull<u8>,
430        layout: Layout
431    ) -> Result<(), <A as AllocError>::Error> {
432        (*self).try_dealloc(ptr, layout)
433    }
434}
435
436impl<A: Grow + ?Sized> GrowMut for A {
437    #[cfg_attr(miri, track_caller)]
438    #[inline(always)]
439    unsafe fn grow_mut(
440        &mut self,
441        ptr: NonNull<u8>,
442        old_layout: Layout,
443        new_layout: Layout
444    ) -> Result<NonNull<u8>, <A as AllocError>::Error> {
445        (*self).grow(ptr, old_layout, new_layout)
446    }
447
448    #[cfg_attr(miri, track_caller)]
449    #[inline(always)]
450    unsafe fn zgrow_mut(
451        &mut self,
452        ptr: NonNull<u8>,
453        old_layout: Layout,
454        new_layout: Layout
455    ) -> Result<NonNull<u8>, <A as AllocError>::Error> {
456        (*self).zgrow(ptr, old_layout, new_layout)
457    }
458}
459
460impl<A: Shrink + ?Sized> ShrinkMut for A {
461    #[cfg_attr(miri, track_caller)]
462    #[inline(always)]
463    unsafe fn shrink_mut(
464        &mut self,
465        ptr: NonNull<u8>,
466        old_layout: Layout,
467        new_layout: Layout
468    ) -> Result<NonNull<u8>, <A as AllocError>::Error> {
469        (*self).shrink(ptr, old_layout, new_layout)
470    }
471}
472
473impl<A: Realloc + ?Sized> ReallocMut for A {
474    #[cfg_attr(miri, track_caller)]
475    #[inline(always)]
476    unsafe fn realloc_mut(
477        &mut self,
478        ptr: NonNull<u8>,
479        old_layout: Layout,
480        new_layout: Layout
481    ) -> Result<NonNull<u8>, <A as AllocError>::Error> {
482        (*self).realloc(ptr, old_layout, new_layout)
483    }
484
485    #[cfg_attr(miri, track_caller)]
486    #[inline(always)]
487    unsafe fn rezalloc_mut(
488        &mut self,
489        ptr: NonNull<u8>,
490        old_layout: Layout,
491        new_layout: Layout
492    ) -> Result<NonNull<u8>, <A as AllocError>::Error> {
493        (*self).rezalloc(ptr, old_layout, new_layout)
494    }
495}
496
497// no AllocMut for &mut A: AllocMut because rust is dumb and "downstream crates may implement Alloc
498// for &mut A: AllocMut"
499
500const LOCK_ERR: Error = Error::Other("lock_failed");
501
502// TODO: decide on inlining for the below
503macro_rules! impl_alloc_for_sync_mutalloc {
504    ($t:ty, $borrow_call:ident) => {
505        impl<A: AllocError + ?Sized> AllocError for $t {
506            type Error = A::Error;
507        }
508
509        impl<A: AllocMut + ?Sized> Alloc for $t {
510            #[cfg_attr(miri, track_caller)]
511            fn alloc(
512                &self,
513                layout: Layout
514            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
515                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
516                    .alloc_mut(layout)
517            }
518
519            #[cfg_attr(miri, track_caller)]
520            fn zalloc(
521                &self,
522                layout: Layout
523            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
524                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
525                    .zalloc_mut(layout)
526            }
527        }
528
529        impl<A: DeallocMut + ?Sized> Dealloc for $t {
530            #[track_caller]
531            unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
532                match self.$borrow_call() {
533                    Ok(mut guard) => guard.dealloc_mut(ptr, layout),
534                    Err(_) => default_dealloc_panic(ptr, layout, LOCK_ERR),
535                }
536            }
537
538            #[cfg_attr(miri, track_caller)]
539            unsafe fn try_dealloc(
540                &self,
541                ptr: NonNull<u8>,
542                layout: Layout
543            ) -> Result<(), <$t as AllocError>::Error> {
544                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
545                    .try_dealloc_mut(ptr, layout)
546            }
547        }
548
549        impl<A: GrowMut + ?Sized> Grow for $t {
550            #[cfg_attr(miri, track_caller)]
551            unsafe fn grow(
552                &self,
553                ptr: NonNull<u8>,
554                old_layout: Layout,
555                new_layout: Layout,
556            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
557                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
558                    .grow_mut(ptr, old_layout, new_layout)
559            }
560
561            #[cfg_attr(miri, track_caller)]
562            unsafe fn zgrow(
563                &self,
564                ptr: NonNull<u8>,
565                old_layout: Layout,
566                new_layout: Layout,
567            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
568                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
569                    .zgrow_mut(ptr, old_layout, new_layout)
570            }
571        }
572
573        impl<A: ShrinkMut + ?Sized> Shrink for $t {
574            #[cfg_attr(miri, track_caller)]
575            unsafe fn shrink(
576                &self,
577                ptr: NonNull<u8>,
578                old_layout: Layout,
579                new_layout: Layout,
580            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
581                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
582                    .shrink_mut(ptr, old_layout, new_layout)
583            }
584        }
585
586        impl<A: ReallocMut + ?Sized> Realloc for $t {
587            #[cfg_attr(miri, track_caller)]
588            unsafe fn realloc(
589                &self,
590                ptr: NonNull<u8>,
591                old_layout: Layout,
592                new_layout: Layout,
593            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
594                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
595                    .realloc_mut(ptr, old_layout, new_layout)
596            }
597
598            #[cfg_attr(miri, track_caller)]
599            unsafe fn rezalloc(
600                &self,
601                ptr: NonNull<u8>,
602                old_layout: Layout,
603                new_layout: Layout,
604            ) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
605                tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
606                    .rezalloc_mut(ptr, old_layout, new_layout)
607            }
608        }
609    };
610}
611
612#[cfg(feature = "std")]
613impl_alloc_for_sync_mutalloc! {
614    ::std::sync::Mutex<A>, lock
615}
616#[cfg(feature = "std")]
617impl_alloc_for_sync_mutalloc! {
618    ::std::sync::RwLock<A>, write
619}
620impl_alloc_for_sync_mutalloc! {
621    ::core::cell::RefCell<A>, try_borrow_mut
622}