error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> src/future/prio_retry.rs:83:33
|
81 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
| ---- help: consider changing this to be mutable: `mut self`
82 | loop {
83 | match Pin::new(&mut self.stream).poll_next(cx) {
| ^^^^ cannot borrow as mutable
impl<S> Stream for PrioRetry<S>
where
S: Stream,
S::Item: Ord + Clone + Eq,
{
type Item = S::Item;
type Error = Error<S::Error>;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
loop {
match self.stream.poll() {
Ok(Async::NotReady) => {
break;
}
Ok(Async::Ready(Some(new_item))) => {
// check if we currently have a delay item
if let Some(ref mut delayed_item) = self.delayed_item {
if delayed_item.value < new_item {
// we have new item, this one will be yielded instantly
self.delayed_item = Some(DelayedItem::new(new_item.clone()));
return Ok(Async::Ready(Some(new_item)));
} else if delayed_item.value == new_item {
// if the current item was requeued, then we will yield it with a backoff
delayed_item.exp_backoff(self.delay_duration);
}
} else {
// we have new item, this one will be yielded instantly
self.delayed_item = Some(DelayedItem::new(new_item.clone()));
return Ok(Async::Ready(Some(new_item)));
}
}
Ok(Async::Ready(None)) => {
return Ok(Async::Ready(None));
}
Err(e) => {
return Err(Error(Kind::Inner(e)));
}
}
}
if let Some(ref mut delayed_item) = self.delayed_item {
if let Some(ref mut delay) = delayed_item.delay {
match delay.poll() {
Ok(Async::NotReady) => {}
Ok(Async::Ready(())) => {
// we yield a clone, since we need the old copy to check if an item was requeued
delayed_item.pause();
return Ok(Async::Ready(Some(delayed_item.value.clone())));
}
Err(e) => {
return Err(Error(Kind::Timer(e)));
}
}
}
};
Ok(Async::NotReady)
}
}
i update this from futures 0.1 to 0.3 can you help me do a more grateful way to impl it?
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/future/prio_retry.rs:96:54
|
89 | if let Some(ref mut delayed_item) = self.delayed_item {
| ---- mutable borrow occurs here
...
96 | delayed_item.exp_backoff(self.delay_duration);
| ----------- ^^^^ immutable borrow occurs here
| |
| mutable borrow later used by call
Since the self is now Poll<&mut Self> not &mut Self, every field access requires .deref() or .deref_mut() method so compiler cannot treat each fields as disjoint borrow. As a workaround you can distruct references of all field at the start of the function and use these variables.
Rust is being pedantic here about order of evaluation. foo.bar(baz) evaluates foo first, baz second.
delayed_item is from self and is mutable, so it has exclusive access to self. So Rust enforces that exclusive "lock" for the call as soon as delayed_item is "evaluated", so when it looks at self.delay_duration, self is already "locked" by delayed_item.
The solution is trivial — cache delay_duration in a variable.
let delay_duration = self.delay_duration;
if let Some(ref mut delayed_item) = self.delayed_item {
delayed_item.exp_backoff(delay_duration);