ELSEIF
Your brief EB
283 stories from 101 feeds 312 clusters Refreshed 2 minutes ago next pull 19:07

TECH Signal 389

SBCL rejects simple-array (unsigned-byte 16) slots when initialized with literal vectors

Illustration only Photo by Maarten Deckers on Unsplash

In SBCL, struct fields declared as (simple-array (unsigned-byte 16)) fail type checks when given literal vectors like #1A(1 2 3) or empty #1A().

WHY IT MATTERS

The mismatch causes runtime errors during struct construction, breaking code that assumes literal vectors satisfy the declared array type. Knowing that SBCL treats literal vectors as SIMPLE-VECTOR and that upgraded-array-element-type influences the check lets developers avoid subtle bugs by constructing arrays with an explicit element type.

Written by elseif from the cluster below · every claim links back to a source

The three things worth knowing

01

Literal vector literals are read as SIMPLE-VECTOR types, not as SIMPLE-ARRAY with the specified element type.

02

Type checks against (simple-array (unsigned-byte 16)) fail for both empty and non-empty literals, causing struct creation errors.

03

Using make-array with :element-type '(unsigned-byte 16) produces a value whose type matches the declared slot, avoiding the issue.

THE READ

What the cluster adds up to.

ORIGINAL ANALYSIS

The author observed that a struct declared with a slot type (simple-array (unsigned-byte 16)) cannot be instantiated with a literal vector. Creating an instance with (make-b :b #1A(1 2 3)) raises an error, and even the default empty literal #1A() triggers the same failure. The type-of the literals is reported as (SIMPLE-VECTOR 0) or (SIMPLE-VECTOR 3), which are not subtypes of the declared (simple-array (unsigned-byte 16)).

SBCL’s handling stems from its array representation optimisations. When an array is created, the implementation may upgrade the element type to a supertype; for unconstrained types like INTEGER the upgraded type is T, but for constrained types like (UNSIGNED-BYTE 16) the upgraded type remains (UNSIGNED-BYTE 16). Because the reader macro produces a SIMPLE-VECTOR without element-type information, the compiler cannot prove it is a subtype of the required simple-array, leading to the failed typep checks.

The practical workaround is to construct the array explicitly with make-array, specifying :element-type '(unsigned-byte 16). This yields a value whose type is (SIMPLE-ARRAY (UNSIGNED-BYTE 16) *), satisfying the struct slot type and allowing default construction. The cost is a few extra lines of code and the need to avoid the convenient literal syntax, which may slightly increase code verbosity and initialization overhead.

For engineers, the issue highlights a portability pitfall: code that relies on reader literals for typed arrays may work on some implementations but fail on SBCL or any system that performs similar element-type upgrades. Explicit array creation ensures consistent behaviour across implementations and avoids surprising runtime type errors in production systems.

In summary, when a struct slot requires a constrained simple-array type, avoid using literal vectors; instead, use make-array with the appropriate :element-type. This aligns the runtime type with the declared type and prevents the type-check failures demonstrated in the example.

Written by elseif from the cluster below · checked for specifics the sources never contained

THE CLUSTER

Same story, 1 feed.

ORDERED BY FIRST SEEN
simondobson.org via Lobsters Unexpected (to me) behaviour in Lisp sub-typing Open ↗