Mutability transmute with a lifetime

Hi, I'm working on a project and I use an external crate. Inside the crate, there is a type that wraps a Write like this:

pub struct SomeType<W: Write> {
    writer: W
}

Now, the crate offers a function to get a shared reference to the inner writer:

fn get_ref(&self) -> &W

However, I also need a way to get a mutable reference to the writer, which the crate does not define.
So, I made a custom trait and implemented it on the type like this (simplified):

impl GetMutRef<W: Write> {
    fn get_mut_ref(&mut self) -> &mut W;
}

impl<W: Write> GetMutRef<W> for SomeType<W> {
    fn get_mut_ref<'a>(&'a mut self) -> &'a mut W {
        #[allow(mutable_transmutes)]
        unsafe { std::mem::transmute(self.get_inner_writer_ref()) }
    }
}

And I know that transmute itself is extremely unsafe and it does not even allow mutability transmutes by default, so all of this looks extremely sketchy even to me. However, as the get_mut_ref function takes a mutable reference to self - even if it does not technically use it - I think it still enforces compile-time borrow-checking and therefore it may actually be safe.
Is this true?

No, it is always unsound to transmute an immutable reference to a mutable reference.

If a reference is immutable, that is a promise to the optimizer that it can assume that the pointee is never written to, which is clearly violated in your case, so you may get incorrect optimizations applied to your code.

1 Like