> But I would argue there's no practical difference between "crash due to segfault" and "panic due to index overflow
One leads to undefined behavior and is potentially exploitable in a way that allows for full control over your program's execution. That's the difference.
No one is arguing that the bug you've described isn't expressible in Rust - it obviously is. It's just not what the borrow checker is for because the borrow checker is for memory safety issues, and you're describing a logical bug.
From a security perspective, yes Rust is better, but it's still a security issue: if you can make a Rust program panic due to overflow, that's a DoS attack.
I think this description is a very narrow way to look at memory safety (and again: totally ignoring the broader issue of lifetime safety), if I'm going to be honest. In my Rust program, I have two functions `spawnDude()` returning an index and a `despawnDude()` taking an index. In C, i have `malloc()` returning a pointer and `free()` taking a pointer. The lifetime issues are the same: just like I shouldn't `free()` a pointer twice, i shouldn't `despawnDude()` twice, and I shouldn't use a dude after I've despawned him. The implementation could even be very similar: using arenas (which is essentially what the Rust array is) and free-lists.
Again: these were the issues Rust was designed to solve, and the borrow checker is the tool it uses to solve them. And it absolutely does do that, if you use the native Rust constructs: this is the true super-power of Rust. The reason why it's so much easier to work with indexes is because you've deliberately chosen not to have the borrow checker analyze this situation. If that is something you have to do a lot of (and I've seen it a number of times, not just in the project the parent mentioned), it does say something important about how the borrow checker limits the expressive power of the language, if you have to turn it off in this way.
I fail to understand the notion between "memory safety bugs" and "logical bugs"? E.g. logical bug is what can lead to memory safety bugs so I don't quite understand the point being made.
Panics are implemented in the same way as exceptions are in C++, beyond that Rust doesn't have a concept of exceptions at all. Fallibility is expressed in terms of sum types that signal state for success or failure with Result.
> Panics are implemented in the same way as exceptions are in C++
If this is true or at least fundamentally very close to each other, and given that exceptions can be abused for arbitrary code execution [1] [2], then it follows that Rust is no different/safer with respect to that, no?
One leads to undefined behavior and is potentially exploitable in a way that allows for full control over your program's execution. That's the difference.
No one is arguing that the bug you've described isn't expressible in Rust - it obviously is. It's just not what the borrow checker is for because the borrow checker is for memory safety issues, and you're describing a logical bug.