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 · 4 comments
Open

impl<A> Allocator for &mut A #508

sarah-quinones opened this issue Dec 17, 2024 · 4 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
@Amanieu
Copy link
Member

Amanieu commented Jan 14, 2025

Could you give a code example of when this is useful? All of Allocator's methods take &self so you should almost never need a &mut A.

@sarah-quinones
Copy link
Author

type erased allocators are my main use-case

instead of making my type generic over the allocator, i want to make it hold a dyn Allocator + Send to avoid a big number of monomorphizations. given a Send + !Sync allocator (e.g., a bump allocator containing a Cell/UnsafeCell), &mut A is Send but not &A

@cuviper
Copy link
Member

cuviper commented Jan 14, 2025

That also means your type will hold exclusive access to that allocator, so you can't even clone, for example.

@sarah-quinones
Copy link
Author

this is acceptable. my clone uses the global allocator, and clone_in takes an allocator parameter that can be used with explicit clones

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

3 participants