amethyst / shred

Shared resource dispatcher

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Replace unsafe code with safer variant

cynecx opened this issue · comments

I've been digging in some of the internals of shred with emphasis on unsafe code and I've noticed this particular method:

shred/src/cell.rs

Lines 91 to 112 in c1bfcda

pub fn map<U, F>(self, f: F) -> Ref<'a, U>
where
F: FnOnce(&T) -> &U,
U: ?Sized,
{
// Extract the values from the `Ref` through a pointer so that we do not run
// `Drop`. Because the returned `Ref` has the same lifetime `'a` as the
// given `Ref`, the lifetime we created through turning the pointer into
// a ref is valid.
let flag = unsafe { &*(self.flag as *const _) };
let value = unsafe { &*(self.value as *const _) };
// We have to forget self so that we do not run `Drop`. Further it's safe
// because we are creating a new `Ref`, with the same flag, which will
// run the cleanup when it's dropped.
std::mem::forget(self);
Ref {
flag,
value: f(value),
}
}

I can't see why one would use unsafe here, if I am not missing anything crucial here, this could be replaced with a completely safe alternative:

    pub fn map<U, F>(self, f: F) -> Ref<'a, U>
    where
        F: FnOnce(&T) -> &U,
        U: ?Sized,
    {
        let val = Ref {
            flag: self.flag,
            value: f(self.value),
        };

        std::mem::forget(self);

        val
    }

Playground