There's the UnwindSafe marker trait that isn't exactly the same thing but addresses the only real case I've seen for forbidding panics which is FFI.
A lot of panics are placed instead of proper error handling as a cause of happy-path programming. (E.g. all cases of .unwrap())
Some panics are placed not knowing they’re panics. (E.g. indexing, calling a function that panics)
Some panics are legitimately placed by people who want a program to panic at a given place; this may collide with the caller’s desire to use Result and error types.
There are lots of situations where being notified about where the panics live can make your code more robust, because they do sneak in.
https://doc.rust-lang.org/std/macro.unreachable.html
In those cases you strike a deal with the devil. The type system won't help you.
Maybe it's an acceptable tradeoff for readability and efficiency.
Maybe you could have modelled the code so it wasn't necessary.
I think you can divide the use of `unreachable!()` in two cases:
1) As a consequence of style (applying LEM to code)
2) As a consequence of low-level abstractions
One can be avoided by remodelling. The other can be tucked away behind safe interfaces.And I am also not arguing for the use of `unreachable_unchecked!()`.
I am only arguing that in all the other cases mentioned, you can simply avoid panics.
I'm not saying that lint should be enabled by default. It's a highly specialized config, but it's an important protection when it's useful.
Otherwise, like duped said, using get will return an Option<T>, and so you'd either have to use unreachable!() and panic anyway, or you'd have to propagate the error up the call stack and let it affect all the types of those functions (at which point, what is the caller supposed to do about it?).
Or you can use get_unchecked which is unsafe and avoids the bounds check. If you pass the bounds check up higher then you have no risk of panic.
My point is that forbidding code from panicking isn't that useful - you still need to audit the code to make sure it's correct.
And this still won't solve the problem of when you as a programmer know that something is definitely inbound but you can't express the proof in the language. Ultimately this means using `panic` (but you don't want to), dummy default values (but this is just `null` all over again!), adding dependent types (which AFAIK nobody has managed to do in a low level language, and even if it was possible it would add a lot of complexity) or just give up and accept your program cannot be accepted.
https://doc.rust-lang.org/std/panic/fn.catch_unwind.html#not...
And they are common only in two scenarios: if you set panic="abort", or special UB checks that the standard library does. The former is just a simple configuration change, the latter is not really something you can handle in any way.