My first rust borrow head scratcher
The Problem
I’m fairly new to rust, having only read through the rust book and a bit of the nom docs.
I spent more time than I care to admit trying to debug the following borrow issue:
This error appeared when I tried to connect reading from a file to functions
that could parse some parts of a git index file. The unit tests
for the read_header
function worked fine with no compilation or run time
errors. It was only when I started to connect to a file that the compilation
error reared it’s head.
The new function I was writing, and the read_header
function:
(Did I mention I’m new to rust, I’m sure this is pretty rough for most
rustaceans)
How I Debugged
After a bit of head scratching I decided I needed to try and come up with a
minimal example that reproduced the issue. I’ve had experience with the
bmp file format, so I decided to parse a few bytes from a
bmp file. I created a new cargo package with only a main.rs
.
Here is the bmp file parsing in all it’s glory:
This code compiles and runs just fine. Now it’s time to start comparing…
It still took me awhile to see it, but if you look at the simple bmp file
parsing I used unwrap()
. I didn’t care about propagating errors, I just
wanted to quickly get something working.
So I updated read_header
to also use unwrap()
instead of the
question mark operator:
to
this got past the borrow compiler error???
I didn’t show it earlier as it would have stood out a bit with the rest of
the code, but you can see that the new
function ritten returns a result
with an error type:
And if we look at how that error type was defined as:
There is a lifetime specified for the u8 slice in the nom error wrapper. The lifetime came about due to me blindly obeying the following compiler error:
This is mainly a lack of my rust experience. I had a general idea of what lifetimes were, but didn’t really understand the implications in this instance.
The Reason for the Compiler Error
As I now understand the problem:
new
could return anom
variant ofGitStatusError
- the
nom
variant ofGitStatusError
used the u8 slice - The u8 slice was local to
new
This means that the code was trying to send the local slice outside of
new
, when there was an error. When I changed to unwrap()
this
prevented the possibility of an error that referenced the u8 slice and thus
avoided the borrow error.
Update (2021-01-20)
The same night, after I wrote this post, my google fu uncovers a stack overflow question someone had almost two years prior. The SO question is the same underlying issue, https://stackoverflow.com/questions/55184864/nom-parser-borrow-checker-issue. The author of the post has a much more consise example of the issue and I’m assuming the answer is from a more experienced rust person.