Hope you don't mind this side track being here.
Fifty shades of safety
Many things could cause an abnormal app termination and from a user point of view they all "crashes", although there are quite a few different flavours of those: there are traps that we or compiler put deliberately (e.g. in order to preserve safety or precondition invariants), there are crashes (like memory access errors) and there are several sub flavours of either. Here's one giant unsorted list of what we colloquially call "crashes" and possible mitigations:
-
Memory safety violations
Possible mitigations:
- prohibit by having unsafe / safe / utmostsafe "colorisation"
-
Integer arithmetic trapping on overflow, etc
Possible mitigations:
- remove traps (as in C. Does it still have divide by zero traps? Don't remember)
- reduce integer range to exclude a certain bit pattern (e.g. UInt.max or Int.min) and use it for NaN similar to how floating point ops are doing it
- make operations throwing
Notes: to reduce "try" clutter we'd need to remove the "try" keyword. - make operations returning optionals
-
fatalError() / abort() / etc
Possible mitigations:
- make it a throwing function instead.
Notes: if uncaught throwing would propagate all way to the top main function, and if we allow having "throwing" main that would still cause app termination. Alternatively we disallow the top main being throwing and would be forced to catch errors at that level. What do we do (other than showing some error alert) is a further interesting question.
- make it a throwing function instead.
-
Precondition traps
Possible mitigations:
- make precondition a throwing function instead
-
Array access trapping on index being out of bounds
Possible mitigations:
- make it throwing
Notes: to reduce "try" clutter we'd need to remove the "try" keyword. - make it return optional
Notes: this works only with getter.. what about setter? We can make setter returning an optional result (e.g. the previous value) but can we force users to always check the returned value?
- make it throwing
-
Dictionary trapping on duplicate keys
Possible mitigations:
- make it throwing
-
Explicit optional unwrapping trapping on nil
Possible mitigations:
- make it throwing
- remove it and users will always do "if / guard let" checking
-
Implicit optional unwrapping trapping on nil
Possible mitigations:
- make it throwing
- remove it and users will reach out for explicit optional unwrapping
-
Stack overflow crashes
Possible mitigations:
- make all function calls (including getters / setters / didSet / subscripts / etc) throwing. Check stack overflow and throw accordingly.
Notes: to reduce "try" clutter we'd need to remove the "try" keyword. - make stack dynamic, although that's kicking the can down the road and you'd still need to do something else like 1 when heap overflows.
- make all function calls (including getters / setters / didSet / subscripts / etc) throwing. Check stack overflow and throw accordingly.
-
Memory allocation failures
Possible mitigations:
- make all memory allocations returning optional, like good old malloc did.
Notes: this includes class instantiation. Hmmm, what about instantiation of a struct that has reference fields? Should it also return optional? What about copy on write? Many questions here. - make all memory allocations throwing
Notes: as above. Effectively all operations will be throwing, in which case to reduce "try" clutter we'd need to remove the "try" keyword.
- make all memory allocations returning optional, like good old malloc did.
-
Crashes during accessing memory that's not available due to overcommitment
Possible mitigations:
- prohibit memory overcommitment
-
Crashes accessing unmapped memory
Notes: a good example needed here. Can this happen in "utmost safe" mode?
-
Crashes writing to readonly memory
Notes: a good example needed here
-
Other crashes during memory access (e.g. parity errors or disk I/O failure when accessing a paged out memory)
Possible mitigations: ???
-
Hangs due to deadlocks. Not a crash, but good to have it here.
Possible mitigations:
- make the locking operation throwing instead of taking a lock that would otherwise cause a deadlock.
-
Other hangs (infinite loop, etc). Not a crash, but good to have it here.
Notes: Very hard problem to solve, impossible in general case. Equivalent to the halting problem. Possible mitigations could be specifying a maximum execution time and throwing when it is reached.
-
Realtime safety violations
Possible mitigations:
- colourisation. We have @noLocks and @noAllocations for that.
- guaranteeing worst case time complexity relates to the "other hangs" issue before.
I might have forgotten something, additions are welcome.
Is it possible to make a "guaranteed crash free" language (language mode) or a platform? I believe it is possible, just hard.