I was forced to use pointer to workaround the borrow check. Would this cause a memory safety problem?

playground link


pub struct DataRef<'a> {
   index: usize,
   data: &'a LazyData,
}

pub struct MutIter<'a> {
   index: usize,
   data: &'a mut LazyData,
}

impl<'a> Iterator for MutIter<'a> {
   type Item = DataRef<'a>;

   fn next(&mut self) -> Option<Self::Item> {
      if self.data.has(self.index) {
         let index = self.index;
         self.index += 1;

         // // impossible because of borrow rule
         // return Some(DataRef { index, data: self.data });

         // workaround by using unsafe pointer dereference
         unsafe {
            let data: *const LazyData = self.data;
            let data = &*data; // would there be a problem here? 🤔
            return Some(DataRef { index, data });
         }
      }

      self.data.load_more();
      self.next()
   }
}

This is UB. It is UB in Rust to have a mutable and immutable borrows to the same data at the same time.

To answer the title in general:

I was forced to use pointer to workaround the borrow check. Would this cause a memory safety problem?

Usually, yes, absolutely. The borrow checker is not merely a code quality linter. It exists to prevent common memory management errors, and it is usually right. This means that if you think you need to work around it, you are usually wrong.

You shouldn't work around borrow checking. Instead, you should learn the 2 simple rules for writing code that passes the borrow checker:

  1. No mutable aliasing
  2. No references to dropped/un-initialized/invalidated data

Your code violates #1. You are holding a mutable reference to the data, and you create a shared reference to the same data. Even the mere existence of an aliased &mut is instant UB.

In general, if you want a lending iterator, you should redesign your data so that you can use <&mut [T]>::split_first_mut() for iterating over elements of the slice one-by-one, because this method is guaranteed to return disjoint references, so you won't need any unsafe. Example Playground.

3 Likes