[Solved] Borrow doesn't drop? "returning this value requires that"

#1

Hello, rustaceans!
I’m struggling with a problem, glad if someone explain it to me.
So, playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d06fcdc5d812895fd068176090288f1b

As you can see, code doesn’t compile, and complains about double mutable borrowing, though it’s clear that borrow on line 17 must be released on line 21? Why so? I understand that if I return something, it will block another borrow, for the lifetime of “something”, but I don’t understand why compiler doesn’t take in account “block” structure.

1 Like
#2

This was supposed to have been fixed as part of NLL, but was instead deferred to polonius (NLL++ :slight_smile:).

2 Likes
#3

Oh, thank you very much, I thought there is a flaw in my logic I don’t understand.

So this is current limitation of rust? Any way I can solve this? Think even unsafe is no helper here. I can’t imagine of any workaround, only change logic completely.

#4

Maybe you could work around it like this (+/- handling of edge cases)

let (first, rest) = self.stack.split_first_mut().unwrap();

let it = rest.last_mut().unwrap();
if it.el.l != 1 {
    return Ok(&mut it.el);
}

let el = &mut first.el;
unimplemented!()

Apart from that, lifetime hacks are doable with unsafe. You can transmute lifetimes (like this) or cast to a raw pointer and back.

1 Like
#5

Thank you very much for answer. Splitting vector solution gives me no help because in my project index can be arbitrary, and if if it.el.l != 1 { fail, I will have to traverse every other vector’s item.

Github link, though, I find very useful. Need to reed about on lifetime erasion.

#6

It seem to be working!
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=60796a2150c9666f60cd33b14b7011fd

Didn’t think transmute from vec to vec will give me something, but it actually worked!

#7

But wait, there’s more! :slight_smile:

transmute in not necessary: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=309a50f9084ddfe48817c5b0b6753b17

I was trying to make such thing even before posting this question, it just I didn’t explicitly cast to raw mut pointer (it was like unsafe { &mut (*(&mut self.stack))[index] };), and thus not work.