4

Polishing Rust. Temporary Value Dropped While Borrowed | by Tim Keating | Jan, 2...

 3 years ago
source link: https://mrtact.medium.com/polishing-rust-42d9131d1c3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Polishing Rust

Temporary Value Dropped While Borrowed

I am at a point in my Rust development where I have started to identify some… slightly sub-optimal approaches I may have taken in my naïveté. It occurred to me that other people at a similar stage of their Rust journey might benefit from seeing my n00b mistakes and how I fixed them once I had a little bit more insight.

Today’s exercise is this function:

This uses the git2 crate to create a child branch off an existing branch. It takes that parent branch, gets a git reference from it (a type of object in the git internals taxonomy, not a Rust reference), converts it to a Commit object, gets a (Rust) reference to it (because the git2::Repository::branch function takes a &Commit), and then handles the potential error case. All nice and fluent, and straightforward to understand (especially with CLion showing you all the types).

Just one small problem: this won’t compile.

Image for post
Image for post

Because we’re taking a reference to a temporary, when the temporary goes out of scope at the end of my function call chain, the reference is no longer valid, so rustc plays the “Nope!” card.

Following the instruction provided by the compiler (“consider using a ‘let’ binding to create a longer lived value”), I reluctantly restructure the code like so:

Ugh. That is hideous, but it compiles, so ¯\_(ツ)_/¯.

Days and weeks pass. This abomination haunts my dreams.

Note the bit about Polonius. Guided by this comment on the Rust forums, I recently tried compiling it using Polonius, which… did not work. Which I should have known. Polonius won’t fix the fact that I grabbed a reference to a dangling temporary.

So I put on my thinking cap. Aha, says I, it is a &Commit, which is why it has a limited lifetime. If I call to_owned(), that should give me a fully-owned Commit instance that will last until the function returns.

Image for post
Image for post

That fixed my original problem, but since I now have a Commit, I have to pass it as &branch_ref to make the subsequent call work.

Wait a second.

I’m doing something super dumb here. I’m converting a Branch into an owned Commit, taking a reference to it, and then re-owning it. What happens if I just remove .as_ref() and .to_owned()?

🎉🎉🎉 Wiktory! 🎉🎉🎉

As it turns out, I was trying too hard. All I needed to do was convert the owned Branch to an owned Commit and then pass a reference to that in my function call. Note that I also changed the variable name to better reflect its new purpose.

If you’re wrestling with learning Rust, I hope you find this helpful. If you have some Rust code that you feel is suboptimal but you just can’t see how to make it better, hit me up on Twitter at @mrtact.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK