The Lisp standard allows it to be implementation dependent, but in SBCL (which I believe the author of TFA is using), it disables all runtime type and bounds checking. This usually speeds things up negligibly[1] in exchange for allowing all kinds of undefined behavior.
1: If it speeds things up non-negligibly, there's almost always a way to get a similar speedup without setting safety to 0; e.g. if you check your types outside of your hot loops, the compiler is smart enough to omit type-checks inside the loop.
Honestly it's more nuanced than that, and probably not such a big deal.
It's kind of like building in Debug mode in other languages. Internally and for testing, use (safety 3). If the code in question doesn't trigger any errors or warnings, then in most cases it's safe to turn (safety 0) and get the tiny performance boost.
I wouldn't recommend (safety 0) globally, but it's probably fine locally in performance critical code that's been tested well, but I do agree it's probably not worth going to (safety 0) in most cases.
The best solution is a compiler who's (speed 3) optimization level is smart enough to optimize out the unnecessary safety checks from (safety 3). I think SBCL can do that in some cases (the safety checks get optimized for speed, at least).
> If the code in question doesn't trigger any errors or warnings, then in most cases it's safe to turn (safety 0) and get the tiny performance boost.
This is trivially not true. Consider:
(defun foo (x)
(declare (safety 0)
(type x (array fixnum (4)))
[Lots of code that doesn't trigger any warnings])
Then in a different source file doing e.g:
(foo nil)
Nothing good will come of that.
> I wouldn't recommend (safety 0) globally, but it's probably fine locally in performance critical code that's been tested well, but I do agree it's probably not worth going to (safety 0) in most cases.
> The best solution is a compiler who's (speed 3) optimization level is smart enough to optimize out the unnecessary safety checks from (safety 3). I think SBCL can do that in some cases (the safety checks get optimized for speed, at least).
The only thing I can think of is that I communicated things poorly in my comment, because this is nearly exactly what I was saying in my comment.
Sure, that code fails with a memory fault with (safety 0). But I explicitly recommended testing and debugging with (safety 3) first, and in that case it gets a type-error and doesn't crash. Once the broken `(foo nil)` is fixed and it's time to ship a release build to the user, it should be safe to drop down to (safety 0).
I think we both agree that 99.9% of the time it's not worth using (safety 0), though.
1: If it speeds things up non-negligibly, there's almost always a way to get a similar speedup without setting safety to 0; e.g. if you check your types outside of your hot loops, the compiler is smart enough to omit type-checks inside the loop.