Abstraction for making a field sync by making shared reference to it useless

I have a struct which contains two fields, one of them a trait object

struct NeverSync {
    sync_field: usize,
    never_sync_field: Box<dyn FnMut()>,
}

Because I only ever access the trait object in methods that take &mut self, an &self does not allow access to that field. For this reason, I believe it would be sound to write an unsafe impl Send for my type.

Since it occurs to me that that is probably a common phenomenon and I want to minimize the scope of my unsafe code, I want to make an abstraction for it.

Does this attempt at it seem sound?

#[derive(Default)]
pub struct SyncMaker<T>(T);

impl<T> From<T> for SyncMaker<T> {
    fn from(inner: T) -> Self {
        Self(inner)
    }
}

impl<T> AsMut<T> for SyncMaker<T> {
    fn as_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T> SyncMaker<T> {
    pub fn into_inner(self) -> T {
        self.0
    }
}

unsafe impl<T> Sync for SyncMaker<T> {}

This looks fine, this is kind of like how mutex is sync even if it's contents aren't.

2 Likes

Yep that looks sound, I’m using a very similar construct here:

One suggestion is to document the safety requirement well. It feels very easy to want to add something like derive(Debug) or Clone, but those would be unsound.

3 Likes

Thank you both for the verification! I wonder how common mutable only fields are in practice. Do you think this abstraction warrants inclusion in the standard library?

Well, it's not mutable only values, it's unique only values (as opposed to sharable values). I would expect them to be somewhat uncommon.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.