Borrowing error when downgrading `&mut T` to `&T`

I think this limitation is fundamental if you want to use lifetimes as markers for safety in unsafe code. Consider for instance the following useless Cell type:

struct UselessCell<T> {
    inner: T,
}

impl<T> UselessCell {
    fn borrow_mut(&mut self) -> UselessRef<'_, T> {
        UselessRef {
            inner: &mut self.inner as *mut T,
        }
    }
}

struct UselessRef<'lt, T> {
    inner: *mut T,
}

impl<'lt, T> UselessRef<'lt, T> {
    fn get(&self) -> &'lt T {
        unsafe { &*self.inner }
    }

    fn mutate(&mut self) where T: Default {
        unsafe {
            *self.inner = T::default();
        }
    }
}

In this scenario, UselessRef only ever gives out immutable borrows, but it can mutate the wrapped value itself. In order for this not to have catastrophic consequences, it has to be assumed that anything with the 'lt lifetime has a mutable borrow if it was generated from a mutable borrow itself.

1 Like