1 ;;;; This file is for testing typechecking of writes to CLOS object slots
2 ;;;; for code compiled with a (SAFETY 3) optimization policy.
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; While most of SBCL is derived from the CMU CL system, the test
8 ;;;; files (like this one) were written from scratch after the fork
11 ;;;; This software is in the public domain and is provided with
12 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
13 ;;;; more information.
17 (declaim (optimize safety
))
20 ((slot :initarg
:slot
:type fixnum
:accessor slot
)))
21 (defclass foo
/gf
(sb-mop:standard-generic-function
)
22 ((slot/gf
:initarg
:slot
/gf
:type fixnum
:accessor slot
/gf
))
23 (:metaclass sb-mop
:funcallable-standard-class
))
24 (defmethod succeed/sv
((x foo
))
25 (setf (slot-value x
'slot
) 1))
26 (defmethod fail/sv
((x foo
))
27 (setf (slot-value x
'slot
) t
))
28 (defmethod succeed/acc
((x foo
))
30 (defmethod fail/acc
((x foo
))
32 (defmethod succeed/sv
/gf
((x foo
/gf
))
33 (setf (slot-value x
'slot
/gf
) 1))
34 (defmethod fail/sv
/gf
((x foo
/gf
))
35 (setf (slot-value x
'slot
/gf
) t
))
36 (defmethod succeed/acc
/gf
((x foo
/gf
))
38 (defmethod fail/acc
/gf
((x foo
/gf
))
44 (with-test (:name
(:evaluator
))
45 (eval '(setf (slot-value (make-instance 'foo
) 'slot
) 1))
46 (assert (raises-error?
(eval '(setf (slot-value (make-instance 'foo
) 'slot
) t
))
48 (eval '(setf (slot (make-instance 'foo
)) 1))
49 (assert (raises-error?
(eval '(setf (slot (make-instance 'foo
)) t
))
51 (eval '(succeed/sv
(make-instance 'foo
)))
52 (assert (raises-error?
(eval '(fail/sv
(make-instance 'foo
)))
54 (eval '(succeed/acc
(make-instance 'foo
)))
55 (assert (raises-error?
(eval '(fail/acc
(make-instance 'foo
)))
57 (eval '(make-instance 'foo
:slot
1))
58 (assert (raises-error?
(eval '(make-instance 'foo
:slot t
))
60 (eval '(make-instance 'foo
:slot
*one
*))
61 (assert (raises-error?
(eval '(make-instance 'foo
:slot
*t
*))
64 (with-test (:name
(:evaluator
/gf
))
65 (eval '(setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) 1))
66 (assert (raises-error?
67 (eval '(setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) t
))
69 (eval '(setf (slot/gf
(make-instance 'foo
/gf
)) 1))
70 (assert (raises-error?
(eval '(setf (slot/gf
(make-instance 'foo
/gf
)) t
))
72 (eval '(succeed/sv
/gf
(make-instance 'foo
/gf
)))
73 (assert (raises-error?
(eval '(fail/sv
/gf
(make-instance 'foo
/gf
)))
75 (eval '(succeed/acc
/gf
(make-instance 'foo
/gf
)))
76 (assert (raises-error?
(eval '(fail/acc
/gf
(make-instance 'foo
/gf
)))
78 (eval '(make-instance 'foo
/gf
:slot
/gf
1))
79 (assert (raises-error?
(eval '(make-instance 'foo
/gf
:slot
/gf t
))
81 (eval '(make-instance 'foo
/gf
:slot
/gf
*one
*))
82 (assert (raises-error?
(eval '(make-instance 'foo
/gf
:slot
/gf
*t
*))
86 (with-test (:name
(:compiler
))
87 (funcall (compile nil
'(lambda ()
88 (setf (slot-value (make-instance 'foo
) 'slot
) 1))))
89 (funcall (compile nil
'(lambda () (setf (slot (make-instance 'foo
)) 1))))
90 (assert (raises-error?
92 (compile nil
'(lambda () (setf (slot (make-instance 'foo
)) t
))))
94 (funcall (compile nil
'(lambda () (succeed/sv
(make-instance 'foo
)))))
95 (assert (raises-error?
96 (funcall (compile nil
'(lambda () (fail/sv
(make-instance 'foo
)))))
98 (funcall (compile nil
'(lambda () (succeed/acc
(make-instance 'foo
)))))
99 (assert (raises-error?
100 (funcall (compile nil
'(lambda () (fail/acc
(make-instance 'foo
)))))
102 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
1))))
103 (assert (raises-error?
104 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot t
))))
106 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
*one
*))))
107 (assert (raises-error?
108 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
*t
*))))
111 (with-test (:name
(:compiler
:setf
:slot-value
))
112 (assert (raises-error?
114 (compile nil
'(lambda ()
115 (setf (slot-value (make-instance 'foo
) 'slot
) t
))))
119 (with-test (:name
(:compiler
/gf
))
120 (funcall (compile nil
122 (setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) 1))))
123 (funcall (compile nil
'(lambda () (setf (slot/gf
(make-instance 'foo
/gf
)) 1))))
124 (assert (raises-error?
127 '(lambda () (setf (slot/gf
(make-instance 'foo
/gf
)) t
))))
129 (funcall (compile nil
'(lambda () (succeed/sv
/gf
(make-instance 'foo
/gf
)))))
130 (assert (raises-error?
131 (funcall (compile nil
'(lambda ()
132 (fail/sv
/gf
(make-instance 'foo
/gf
)))))
134 (funcall (compile nil
'(lambda () (succeed/acc
/gf
(make-instance 'foo
/gf
)))))
135 (assert (raises-error?
136 (funcall (compile nil
'(lambda ()
137 (fail/acc
/gf
(make-instance 'foo
/gf
)))))
139 (funcall (compile nil
'(lambda () (make-instance 'foo
/gf
:slot
/gf
1))))
140 (assert (raises-error?
141 (funcall (compile nil
'(lambda ()
142 (make-instance 'foo
/gf
:slot
/gf t
))))
144 (funcall (compile nil
'(lambda () (make-instance 'foo
/gf
:slot
/gf
*one
*))))
145 (assert (raises-error?
146 (funcall (compile nil
'(lambda ()
147 (make-instance 'foo
/gf
:slot
/gf
*t
*))))
150 (with-test (:name
(:compiler
/gf
:setf
:slot-value
))
151 (assert (raises-error?
155 (setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) t
))))
159 (with-test (:name
(:slot-inheritance
:slot-value
:float
/single-float
))
160 (defclass a
() ((slot1 :initform
0.0 :type float
)))
161 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
162 (defmethod inheritance-test ((a a
)) (setf (slot-value a
'slot1
) 1d0
))
163 (inheritance-test (make-instance 'a
))
164 (assert (raises-error?
(inheritance-test (make-instance 'b
)) type-error
)))
166 (with-test (:name
(:slot-inheritance
:slot-value
:t
/single-float
))
167 (defclass a
() ((slot1 :initform
0.0)))
168 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
169 (defmethod inheritance-test ((a a
)) (setf (slot-value a
'slot1
) 1d0
))
170 (inheritance-test (make-instance 'a
))
171 (assert (raises-error?
(inheritance-test (make-instance 'b
)) type-error
)))
173 (with-test (:name
(:slot-inheritance
:writer
:float
/single-float
))
174 (defclass a
() ((slot1 :initform
0.0 :type float
:accessor slot1-of
)))
175 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
176 (defmethod inheritance-test ((a a
)) (setf (slot1-of a
) 1d0
))
177 (inheritance-test (make-instance 'a
))
178 (assert (raises-error?
(inheritance-test (make-instance 'b
)) type-error
)))
180 (with-test (:name
(:slot-inheritance
:writer
:float
/single-float
))
181 (defclass a
() ((slot1 :initform
0.0 :accessor slot1-of
)))
182 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
183 (defmethod inheritance-test ((a a
)) (setf (slot1-of a
) 1d0
))
184 (inheritance-test (make-instance 'a
))
185 (assert (raises-error?
(inheritance-test (make-instance 'b
)) type-error
)))
187 (with-test (:name
(:slot-inheritance
:type-intersection
))
197 :type unsigned-byte
)))
200 (setf (slot1-of (make-instance 'a
*)) -
1)
201 (setf (slot1-of (make-instance 'b
*)) (1+ most-positive-fixnum
))
202 (setf (slot1-of (make-instance 'c
*)) 1)
203 (assert (raises-error?
(setf (slot1-of (make-instance 'c
*)) -
1)
205 (assert (raises-error?
(setf (slot1-of (make-instance 'c
*))
206 (1+ most-positive-fixnum
))
208 (assert (raises-error?
(make-instance 'c
* :slot1 -
1)
210 (assert (raises-error?
(make-instance 'c
* :slot1
(1+ most-positive-fixnum
))
214 ((slot1 :initform nil
217 :type
(or null function
))))
219 ((slot1 :initform nil
222 :type
(or null
(function (fixnum) fixnum
)))))
224 (with-test (:name
(:type
:function
))
225 (setf (slot1-of (make-instance 'a
)) (lambda () 1))
226 (setf (slot1-of (make-instance 'b
)) (lambda () 1))
227 (assert (raises-error?
(setf (slot1-of (make-instance 'a
)) 1)
229 (assert (raises-error?
(setf (slot1-of (make-instance 'b
)) 1)
231 (make-instance 'a
:slot1
(lambda () 1))
232 (make-instance 'b
:slot1
(lambda () 1)))
234 (with-test (:name
:alternate-metaclass
/standard-instance-structure-protocol
)
235 (defclass my-alt-metaclass
(standard-class) ())
236 (defmethod sb-mop:validate-superclass
((class my-alt-metaclass
) superclass
)
238 (defclass my-alt-metaclass-instance-class
()
239 ((slot :type fixnum
:initarg
:slot
))
240 (:metaclass my-alt-metaclass
))
241 (defun make-my-instance (class)
242 (make-instance class
:slot
:not-a-fixnum
))
243 (assert (raises-error?
(make-my-instance 'my-alt-metaclass-instance-class
)
246 (with-test (:name
:typecheck-class-allocation
)
247 ;; :CLASS slot :INITFORMs are executed at class definition time
248 (assert (raises-error?
249 (eval `(locally (declare (optimize safety
))
250 (defclass class-allocation-test-bad
()
251 ((slot :initform
"slot"
254 :allocation
:class
)))))
256 (let ((name (gensym "CLASS-ALLOCATION-TEST-GOOD")))
257 (eval `(locally (declare (optimize safety
))
259 ((slot :initarg
:slot
260 :type
(integer 100 200)
261 :allocation
:class
)))))
263 `(macrolet ((check (form)
264 `(assert (multiple-value-bind (ok err
)
265 (ignore-errors ,form
)
267 (typep err
'type-error
)
268 (equal '(integer 100 200)
269 (type-error-expected-type err
)))))))
270 (macrolet ((test (form)
272 (check (eval '(locally (declare (optimize safety
))
274 (check (funcall (compile nil
'(lambda ()
275 (declare (optimize safety
))
277 (test-slot (value form
)
279 (assert (eql ,value
(slot-value (eval ',form
) 'slot
)))
280 (assert (eql ,value
(slot-value (funcall (compile nil
'(lambda () ,form
)))
282 (test (make-instance ',name
:slot
:bad
))
283 (assert (not (slot-boundp (make-instance ',name
) 'slot
)))
284 (let ((* (make-instance ',name
:slot
101)))
286 (test (setf (slot-value * 'slot
) (list 1 2 3)))
287 (setf (slot-value * 'slot
) 110)
289 (test-slot 110 (make-instance ',name
))
290 (test-slot 111 (make-instance ',name
:slot
111)))))))