Work-around lifetime inference difference between mutable and immutable

I found interesting case where the same code doesn't compile

There are two iterators that use index operator to access element of buffer.
While inference works just fine for immutable case, it seems currently compile gets confused for mutable.
All the while the code is basically the same.

While technically I can understand why it might not work (as mutable references are unique and stuff) but I wonder if it would be possible to safely implement something like that? (Do note that I cannot use pointers as memory is not necessary single chunk)

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e0a28a4da090698c2c4c61c966a2ece3

I believe simple trick as &mut *(self.inner[idx] as *mut u8) is possible, but I'm not sure how sound it is

You can't so long as you are depending on the Index* trait. There is no guarantee that the IndexMut trait will give distinct references for distinct indicies. In any case, using indexing like this would likely conflict with Stacked Borrows if you use an array of u8, so it may just be impossible to use the Index* trait for this.

The underlying buffer would need to provide the iter_mut inplementation.

I don't believe I fully follow you.
Even if we assume that Index trait would give non-distinct reference, why would it even matter?
Iterator can return only one reference at the time, so there can be only one borrow at any given time.

I'm also not following you regarding borrows for u8 arrays, but in general we would anyway prefer to use slice rather than array (due to lack of const generics)

The underlying buffer would need to provide the iter_mut inplementation.

This is just plain inefficiency and sadness

let mut iter = your_iterator;
let a: &mut u8 = iter.next().unwrap();
let b: &mut u8 = iter.next().unwrap();
assert_eq!(!ptr::eq(a, b));

This is valid, and should never panic.

There isn't much of a difference between [T] and [T; N] wrt Stacked Borrows.

I see your point, but I'd think that it is a general problem to any IndexMut implementation then as we cannot really guarantee what sort of pointer it returns

Exactly, so you must provide some other way of guaranteeing that IndexMut returns distinct references when given distinct indicies. One way would be to make Buf an unsafe trait which requires this. The other way is to provide a streaming-iterator (although the given streaming iterator implementation won't fit your use-case), but it should be pretty easy to build up your own version of streaming iterator that can yield mutable references

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