How much do you think about borrowing

This fighting with the compiler mostly goes away with practice. It took me a while to "get" it, but borrowing is not a chore any more. I can anticipate what will work and what won't work.

I don't "think" about it in a sense of "oh no, it doesn't work, what am I going to do now!?", but rather something straightforward like "I know another thread is going to need this data, so it's an Arc".

It's sort-of like "thinking" about balancing a bicycle. It may be hard when you start, and you can't ride a bicycle without balance, but once you get it, you only think where you want to go, and execution comes naturally.

You can't write Rust without getting borrowing and ownership correctly. But once you internalize it, and use appropriate programming patterns and data structures, it stops being a chore.

For example, if you don't know about self-referential struct limitation you can waste a whole day on it. If you do, you either avoid this pattern entirely, or know to use Arc or some other workaround, and get on with it.

There are exceptions:

  • once in a while I get surprised that some code doesn't compile. It's usually because the compiler sees a mistake in my logic (e.g. I wanted to use shared data without locking, or a long-lived thread could access to a temporary borrow). That's a good thing!

  • The hard cases are typically in generic code. Getting lifetimes right in higher-order abstractions is much harder than in regular code. This can be a chore and a puzzle.

17 Likes