How I bail myself out of Rust lifetime problems as somebody who probably learned Rust the wrong way (by just trying to build stuff as if it were C/node.js and run into problems instead of slowing down + reading):<p>1. .clone() / .to_owned()<p>1. String -> vs &String/&str with & borrow<p>1. lazy_static / OnceCell + Lazy / OnceLock<p>1. Arc<Mutex<T>> with lots of .lock(). What would start off as like NULL in Java/C is Arc<Mutex<Option<T>>> and you have to check if it is .is_none()<p>I think that's about it. I rarely introduce a lifetime to a struct/impl. I try to avoid it honestly (probably for worse). Arc kind of bails you out of a lot (whether that's for good or not I don't know).<p>edit: Remembered another. I think it's kind of weird/too verbose from the compiler / borrow checker when you have a primitive like u32 and it's borrowed and you had to dereference it or clone it.
I just clone everywhere and write Rust like a high level language. Then, once I need to optimize more, if I ever do (as Rust is many times faster than other languages even with liberal cloning), then I simply go through and remove the clone where needed.
Other tips for understanding Rust lifetime issues:<p>- Enable rust-analyzer inlay hints for elided lifetimes, reborrows, etc<p>- Enable the `elided_lifetimes_in_paths` lint<p>Together, these should ensure that all lifetimes in your code are clearly visible on the screen.
#9 (downgrading mut refs to shared refs) is a big one. It makes things quite a bit more complicated in the context of our work on the OCaml-Rust interface (more precisely the safe interface for the GC). As I understand it, this is not a sacrifice we make at the "Altar of Memory Safety", but one we make at the Altar of Mutex::get_mut and Cell::get_mut, which is a much smaller altar (how often do you find yourself in possession precisely of a mutable borrow of a Mutex or of a Cell?).
I use ChatGPT to ask questions about my code - including rust lifetimes - and usually get pretty good detailed answers. More recently I started using diesel ORM and was pleasantly surprised that the bot can answer questions about diesel usage.
Incredible. I never held the quoted misconception about `T: '*`, but I didn't understand it. It was a known unknown - I simply applied it when told to do so. This is the first time someone has explained it an understandable way, I guess the implications (it's a ref of that lifetime or an owned) are a better explanation than the technical (T is bounded by the lifetime).
About #10:<p>> because to unify them at this point would be a breaking change<p>Couldn't they change this in a future edition without breaking older editions?
Discussed at the time:<p><i>Common Rust Lifetime Misconceptions</i> - <a href="https://news.ycombinator.com/item?id=23279731">https://news.ycombinator.com/item?id=23279731</a> - May 2020 (43 comments)
This is a nice writeup. (5) and (10) are particularly good to know IMO -- (5) makes it pretty easy to design correct-looking APIs that only fail to compile when actually called (versus when defined), and (10) is a significant roadbump in Rust's otherwise relatively smooth (IMO) learning curve.
This is fantastic and definitely hits a few points that confused me when I first started as well. I remember definitively pounding the keyboard in frustration over at least one of these
I stopped reading when he started talking set theory. there's a far simpler way to explain it and learn it. nice way to tie ourselves into knots. no thanks.
This is very helpful. But I find it cumbersome to mix "misconceptions" with "clarifications".<p>To elaborate, stating "Foo is bar" as a misconception to be clarified, and then following it up with "Baz is quux", makes it very hard to follow and clearly identify what bits of information should be ingrained. In my opinion, information should only be conveyed "in the affirmative".<p>For example, don't write "Foo is bar is not true", write "Foo is NOT bar". Or have some consistent and unmistakable typography for the "false statements" (highlighting or color, etc)