They're called panics.
> There's no subtyping, so ClassCastExceptions can't exist.
Any sort of polymorphism opens you up to the possibility that code that's written to take abstract type A, implemented concretely in B and C, implicitly expects a B and blows up when it gets a C. Rust doesn't solve this problem.
> final doens't exist
Sure it does. It's just implied, and not-final has to be spelled out. This is one thing Rust did that I do agree was a good move. The other stuff? I remain unconvinced, especially with respect to structural subtyping.
Nope.
Sure, it's not "recommended", but recommendations don't define semantics.
If hypothetical unreasonable libraries are in scope, they can just open /proc/self/mem for writing (in safe Rust!) and violate memory safety, and that's not an argument that Rust isn't memory safe. So why should hypothetical unreasonable libraries be an argument that Rust has exceptions?
Can you explain this? Do you mean that the type C does not correctly implement A? Do you mean something that expects a specific value from a methid in A that only B will return? Both of those, while possible just seem like a complaint of "X doesn't prevent me from purposely breaking it".
Unwrap should always be suspect. It's easy to turn it into a pattern matcher instead, which explicitly forces you to hand the none case.
I'm not saying you're wrong, but I don't think it's an example of an error created by a polymorphic type. (Instances of the same type can do this as well.)
One could actually even express the Option concept as a trait, with manual downcasts:
trait OptionLike {
type Contained;
fn is_some(self) -> bool;
fn as_some(self) -> Some<Self::Contained>;
}
struct Some<T> { value: T }
impl<T> OptionLike for Some<T> { ... }
struct None<T> { _phantom: ...<T> }
impl<T> OptionLike for None<T> { ... }
Under this scheme, Option<T> is expressed as a trait object like Box<OptionLike<Contained=T>>, and the whole thing looks a lot more like the OOP/subclassing approach.In any case, the fact that unwrap is clearly documented to fail on the None case is orthogonal: it's an invariant about the (sub)types of it's arguments that isn't expressed in the signature.
I agree Rust doesn’t solve all bugs.
* There is no reflection API
* Exceptions don't exist
* There's no subtyping, so ClassCastExceptions can't exist. (There's subtyping with lifetimes, and you can't cast them, so that doesn't count)
* final doens't exist
That said, every language has things that you don't realize; we did have a sort of similar moment to this stuff before 1.0 with the "leakapocalypse." Rust will have its own issues. But it doesn't really inherit the problems you're talking about above.