Clozure / ccl

Clozure Common Lisp
http://ccl.clozure.com
Apache License 2.0
853 stars 103 forks source link

Can't set array-typed class slot value with accessor #291

Open sjl opened 4 years ago

sjl commented 4 years ago

I've got a class with a slot of type (simple-array (unsigned-byte 54) (* *)) (the 54 is not a typo, I have something that needs fifty-four bits (I'm aware it'll get upgraded to fixnum on 64-bit linux x86)). When I attempt to set this slot to the result of (make-array ...) of the proper type with its accessor, it fails:

? (defclass foo () ((x :accessor x :type (simple-array (unsigned-byte 54) (* *)))))
#<STANDARD-CLASS FOO>

? (setf (x (make-instance 'foo))  (make-array (list 3 4) :element-type '(unsigned-byte 54)))
> Error: The value #<ARRAY 3x4 type (UNSIGNED-BYTE 64), simple> can not be used to set the value of the slot X in #<FOO #x3020004C4B5D>, because it is not of type (SIMPLE-ARRAY (UNSIGNED-BYTE 54) (* *)).
> While executing: CCL::%MAYBE-STD-SETF-SLOT-VALUE-USING-CLASS, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
1 > :pop

? (lisp-implementation-version)
"Version 1.12-dev (v1.12-dev.5-23-gb25693fa) LinuxX8664"

Using slot-value instead of the accessor succeeds:

? (setf (slot-value (make-instance 'foo) 'x)  (make-array (list 3 4) :element-type '(unsigned-byte 54))) 
#2A((0 0 0 0) (0 0 0 0) (0 0 0 0)) 

Storing the array in a variable and using that with the accessor also succeeds:

? (defparameter *x* (make-array (list 3 4) :element-type '(unsigned-byte 54))) 
*X* 

? (setf (x (make-instance 'foo)) *x*) 
#2A((0 0 0 0) (0 0 0 0) (0 0 0 0)) 
phoe commented 4 years ago

Brief analysis: The function %MAYBE-STD-SETF-SLOT-VALUE-USING-CLASS mentioned in the stack trace is:

https://github.com/Clozure/ccl/blob/275105afd94706d95ac955178316074931822c42/level-1/l1-clos-boot.lisp#L2836-L2851

It calls an inlined function named %SET-STD-SLOT-VECTOR-VALUE:

https://github.com/Clozure/ccl/blob/275105afd94706d95ac955178316074931822c42/level-1/l1-clos-boot.lisp#L2805-L2823

The BAD-SLOT-TYPE error is signaled from here. Likely TYPE and TYPE-PREDICATE are mismatched in some way.