I've heard that "Rust's borrow checker is necessary to ensure memory safety without a GC" usually also implying it's the only way, but I've done the same without the borrow checker. Am I just clueless/confused?
Context (skip ahead if you don't need the context):
So for context, I've been making a programming language for 1.5 years now. I recently introduced automatic lifetime detection and coupling to ensure some memory safety problems I had initially overlooked. These problems usually were about interior mutability, usually structs with reference type members.
After doing this update, I believe my language to be memory safe. (I say "believe" because the language is still not in 1.0 yet and I've probably forgotten something big)
My language makes a few assumptions here:
\- all references exist purely on the stack (even if that isn't actually true)
\- you can only return references if they were passed in as arguments. (aka they have the "long" lifetime)
\- that previously mentioned return-ability is inherited for compound types like structs and arrays.
\- All functions return data with a short lifetime, even if returning long-lived data.
\- Lifetimes get "coupled" to each other when certain rules must be followed. This happens for arguments in a function that somehow rely on each other (and are lifetime tracked).
\- Everything is passed in by copy (with obvious optimizations for arrays, structs, etc that copy internally but pass by pointer)
\- the UntypedPointer type is unchecked for all the usual checks that references have, it is the "unsafe type". It can also be casted to any pointer type.
Coupling example:
This is bad code ofc. It was just meant to error on purpose. I was fixing that error message.
The real question:
Okay, with that all over with (sorry), my question is: why do a lot of people argue that rust's borrow checker is the only way to achieve memory safety without a GC?
Have I simply been misunderstanding what people have been saying? I swear I can distinctly remembers having conversations about how Rust's approach is the only way to achieve memory safety without a GC.
I don't know, maybe I'm confused or dumb. I have someone also telling me that this could "arguably be considered borrow checking". I'm not sure since I feel it is much simpler (to use at least) than rust's borrow checking and lifetimes (which I did on purpose).
I just know the rust community is pretty smart when it comes to this kind of thing, so I thought it couldn't hurt to ask