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}