Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl<A> Allocator for &mut A #508

Open
sarah-quinones opened this issue Dec 17, 2024 · 0 comments
Open

impl<A> Allocator for &mut A #508

sarah-quinones opened this issue Dec 17, 2024 · 0 comments
Labels
api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api

Comments

@sarah-quinones
Copy link

sarah-quinones commented Dec 17, 2024

Proposal

add an Allocator impl for &mut A when A: ?Sized + Allocator that forwards to the underlying implementation

Problem statement

&mut A currently doesn't impl Allocator when A does

Motivating examples or use cases

the current state of things makes it cumbersome to work with Send allocators (especially type erased dyn 'a + Send + Allocator). examples of allocators that are Send, but not Sync are local allocators that wrap a RefCell to satisfy the immutable ref api.

Solution sketch

we can just copy the &A implementation

unsafe impl<A> Allocator for &mut A
where
    A: Allocator + ?Sized,
{
    #[inline]
    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        (**self).allocate(layout)
    }

    #[inline]
    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        (**self).allocate_zeroed(layout)
    }

    #[inline]
    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
        // SAFETY: the safety contract must be upheld by the caller
        unsafe { (**self).deallocate(ptr, layout) }
    }

    #[inline]
    unsafe fn grow(
        &self,
        ptr: NonNull<u8>,
        old_layout: Layout,
        new_layout: Layout,
    ) -> Result<NonNull<[u8]>, AllocError> {
        // SAFETY: the safety contract must be upheld by the caller
        unsafe { (**self).grow(ptr, old_layout, new_layout) }
    }

    #[inline]
    unsafe fn grow_zeroed(
        &self,
        ptr: NonNull<u8>,
        old_layout: Layout,
        new_layout: Layout,
    ) -> Result<NonNull<[u8]>, AllocError> {
        // SAFETY: the safety contract must be upheld by the caller
        unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) }
    }

    #[inline]
    unsafe fn shrink(
        &self,
        ptr: NonNull<u8>,
        old_layout: Layout,
        new_layout: Layout,
    ) -> Result<NonNull<[u8]>, AllocError> {
        // SAFETY: the safety contract must be upheld by the caller
        unsafe { (**self).shrink(ptr, old_layout, new_layout) }
    }
}

Alternatives

an alternative solution is using a ByMut<A> wrapper that's a thin wrapper over &mut A, but this is an unnecessary hoop to make users jump through

@sarah-quinones sarah-quinones added api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api labels Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api
Projects
None yet
Development

No branches or pull requests

1 participant