1. Promises from the programmer to the compiler. These allow the compiler to generate better machine code by avoiding having to check for things that the programmer promises not to do.
2. Restrictions from one programmer to another. These allow a library author to stop a library user from calling their functions with data that they aren't able to handle. (Enforced by the compiler, of course.)
1 is obsolete. Modern language runtimes can use internal typing, speculation, and side exits to automatically make the speed improvements with no loss of generality.
@WomanCorn Some of us still hack on kernels, where your program *is* the runtime.
As https://www.usenix.org/system/files/1311_05-08_mickens.pdf puts it, "if you find yourself drinking a martini and writing programs in garbage-collected, object-oriented Esperanto, be aware that the only reason that the Esperanto runtime works is because there are systems people who have exchanged any hope of losing their virginity for the exciting opportunity to think about hex numbers"
Sparse is a great way to extend the C type system; sure, it's no ML type calculus, but it gives us a lot of the things we need (e.g. __user pointers, endian annotations).