Unexpected (to me) behaviour in Lisp sub-typing
In a recent encounter, a programmer discovered unexpected behavior in how Common Lisp, specifically SBCL, handles array sub-typing. The issue arises when attempting to specialize a simple-array type against a constrained type like (unsigned-byte 16).
When creating instances of a struct with specific initial values, the values are type-checked. Omitting the argument results in the default value specified in the declaration. However, when specializing the simple-array type against (unsigned-byte 16), an error occurs, as does using the default value. This behavior puzzled the programmer, who traced the issue back to the fact that #1A() is given type (simple-vector 0) while #1A(1 2 3) is given type (simple-vector 3), neither of which are sub-types of (simple-array (unsigned-byte 16)).
The compiler's behavior appears to be optimizing the storage of arrays with specific types, making it challenging to compare against types like simple-vector that lack their element type. This explains why the check succeeds for types like integer, whose values are stored boxed and can be represented uniformly. However, the behavior is not explicitly detailed in the manuals or elsewhere, and it seems to be related to the upgraded array element type.
The compiler is allowed to use a different type for the array's representation, which must be a supertype of the requested type. This suggests that SBCL optimizes the representation and performs more detailed type-checking for elements. While making the type of the value explicit can help avoid the issue, the root cause lies in the compiler's optimization and type-checking process for constrained types.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.