Whether slot types are being checked or not is undefined for both structures and CLOS instances.

Many implementations will do it for structures - but not all.

Few implementations will do it for CLOS instances - Clozure CL actually does it for example.

SBCL also can check CLOS slot types - when safety is high:

* (declaim (optimize safety)) NIL * (progn (defclass foo-class () ((bar :initarg :bar :type list))) (make-instance 'foo-class :bar 'some-symb)) debugger invoked on a TYPE-ERROR: The value SOME-SYMB is not of type LIST. Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level. ((SB-PCL::SLOT-TYPECHECK LIST) SOME-SYMB) 0]

How to do it otherwise?

This is kind of an advanced subject which probably needs some CLOS meta-object-protocol hackery. Two variants:

define a method for SHARED-INITALIZE which checks the init arguments.

define a metaclass for your class and a method on SET-SLOT-VALUE-USING-CLASS . But then you need to be sure that your implementation actually provides AND uses SET-SLOT-VALUE-USING-CLASS. This is a generic function, which is part of the MOP. Some implementations provide it, but some are only using it when requested (otherwise setting a slot may get a speed penalty).

For the latter here is self-built SBCL version to check types for writing slots:

First the metaclass:

; first a metaclass for classes which checks slot writes (defclass checked-class (standard-class) ()) ; this is a MOP method, probably use CLOSER-MOP for a portable version (defmethod sb-mop:validate-superclass ((class checked-class) (superclass standard-class)) t)

Now we check all slot writes for that metaclass:

; this is a MOP method, probably use CLOSER-MOP for a portable version (defmethod (setf sb-mop:slot-value-using-class) :before (new-value (class checked-class) object slot) (assert (typep new-value (sb-mop:slot-definition-type slot)) () "new value ~a is not of type ~a in object ~a slot ~a" new-value (sb-mop:slot-definition-type slot) object slot))

Our example class uses that metaclass:

(defclass foo-class () ((bar :initarg :bar :type list)) (:metaclass checked-class))

Using it: