I want to access and manipulate active_outer_index_iterator
and current_outer_index
within trait ISequentialOuterIndexRemoverV1
. They will be used in function load_outer_index()
which is a default trait implementation.
Since this trait will also be applied on another struct with different inner fields, I am not implementing load_outer_index()
directly on SequentialOuterIndexRemover
.
/// Helper to sequentially read and remove outer indices from the index list
/// in slot storage
pub struct SequentialOuterIndexRemover<'a> {
/// Iterator to read active outer indices from index list
pub active_outer_index_iterator: ActiveOuterIndexIteratorV2<'a>,
/// The currently read outer index
pub current_outer_index: Option<OuterIndex>,
}
pub trait ISequentialOuterIndexRemoverV1<'a> {
fn active_outer_index_iterator(&'a mut self) -> &'a mut ActiveOuterIndexIteratorV2;
fn current_outer_index(&mut self) -> &mut Option<OuterIndex>;
}
So far I tried two solutions:
I added load_outer_index()
to the trait and tried to access active_outer_index_iterator()
and current_outer_index()
. I am getting error 'cannot borrow *self
as mutable more than once at a time'.
pub trait ISequentialOuterIndexRemoverV1<'a> {
fn active_outer_index_iterator(&'a mut self) -> &'a mut ActiveOuterIndexIteratorV2;
fn current_outer_index(&mut self) -> &mut Option<OuterIndex>;
// Error
// rustc: cannot borrow `*self` as mutable more than once at a time
// second mutable borrow occurs here
fn load_outer_index(&'a mut self, ctx: &mut ArbContext) {
*self.current_outer_index() = self.active_outer_index_iterator().next(ctx);
}
}
I tried the solution from https://stackoverflow.com/a/26194992/27713386. I removed <'a> from top of the trait and added it to the function. The trait compiles but now I am unable to write implementation for active_outer_index_iterator()
. I am puzzled with the compiler error because both signatures seem to be the same.
rustc: method not compatible with trait
expected signature `fn(&'a mut SequentialOuterIndexRemover<'_>) -> &'a mut ActiveOuterIndexIteratorV2<'a>`
found signature `fn(&'a mut SequentialOuterIndexRemover<'_>) -> &'a mut ActiveOuterIndexIteratorV2<'a>`
pub trait ISequentialOuterIndexRemover {
// <'a> removed from above and added to this function
fn active_outer_index_iterator<'a>(&'a mut self) -> &mut ActiveOuterIndexIteratorV2;
fn current_outer_index(&mut self) -> &mut Option<OuterIndex>;
// Works now
fn load_outer_index<'a>(&'a mut self, ctx: &mut ArbContext) {
*self.current_outer_index() = self.active_outer_index_iterator().next(ctx);
}
}
impl<'a> ISequentialOuterIndexRemover for SequentialOuterIndexRemover<'a> {
// rustc: method not compatible with trait
// expected signature `fn(&'a mut SequentialOuterIndexRemover<'_>) -> &'a mut ActiveOuterIndexIteratorV2<'a>`
// found signature `fn(&'a mut SequentialOuterIndexRemover<'_>) -> &'a mut ActiveOuterIndexIteratorV2<'a>`
fn active_outer_index_iterator<'a>(&'a mut self) -> &mut ActiveOuterIndexIteratorV2 {
&mut self.active_outer_index_iterator
}
fn current_outer_index(&mut self) -> &mut Option<OuterIndex> {
&mut self.current_outer_index
}
}
As pointed by Jmb, I forgot to add lifetime <'a>
on the method when posting the question. The issue persists even after editing.
struct InnerStruct<'a> {
data: &'a mut u8,
}
struct MyStruct<'a> {
inner: InnerStruct<'a>,
cache: u8,
}
trait GetInnerMut<'a> {
fn get_inner_mut(&'a mut self) -> &mut InnerStruct;
fn get_cache(&mut self) -> &mut u8;
fn process(&'a mut self) {
let inner_mut = self.get_inner_mut();
// rustc: cannot borrow `*self` as mutable more than once at a time
// second mutable borrow occurs here
*self.get_cache() = *inner_mut.data;
}
}
impl<'a> GetInnerMut<'a> for MyStruct<'a> {
fn get_inner_mut(&'a mut self) -> &mut InnerStruct {
&mut self.inner
}
fn get_cache(&mut self) -> &mut u8 {
&mut self.cache
}
}
You stuck the 'a
lifetime in the wrong spot. It parameterizes InnerStruct
, not &mut self
. You can kind of see this if you peel back the layers: the lifetime of &mut self.inner
is obviously the same as that of &mut self
, but the data contained therein has the separate lifetime of 'a
.
struct InnerStruct<'a> {
data: &'a mut u8,
}
struct MyStruct<'a> {
inner: InnerStruct<'a>,
cache: u8,
}
trait GetInnerMut<'a> {
fn get_inner_mut(&mut self) -> &mut InnerStruct<'a>;
}
impl<'a> GetInnerMut<'a> for MyStruct<'a> {
fn get_inner_mut(&mut self) -> &mut InnerStruct<'a> {
&mut self.inner
}
}