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.
15 ;;; Typechecking should be working, but it isn't.
16 #+interpreter
(sb-ext:exit
:code
104)
20 (declaim (optimize safety
))
23 ((slot :initarg
:slot
:type fixnum
:accessor slot
)))
24 (defclass foo
/gf
(sb-mop:standard-generic-function
)
25 ((slot/gf
:initarg
:slot
/gf
:type fixnum
:accessor slot
/gf
))
26 (:metaclass sb-mop
:funcallable-standard-class
))
27 (defmethod succeed/sv
((x foo
))
28 (setf (slot-value x
'slot
) 1))
29 (defmethod fail/sv
((x foo
))
30 (setf (slot-value x
'slot
) t
))
31 (defmethod succeed/acc
((x foo
))
33 (defmethod fail/acc
((x foo
))
35 (defmethod succeed/sv
/gf
((x foo
/gf
))
36 (setf (slot-value x
'slot
/gf
) 1))
37 (defmethod fail/sv
/gf
((x foo
/gf
))
38 (setf (slot-value x
'slot
/gf
) t
))
39 (defmethod succeed/acc
/gf
((x foo
/gf
))
41 (defmethod fail/acc
/gf
((x foo
/gf
))
47 (with-test (:name
(:evaluator
))
48 (eval '(setf (slot-value (make-instance 'foo
) 'slot
) 1))
49 (assert-error (eval '(setf (slot-value (make-instance 'foo
) 'slot
) t
))
51 (eval '(setf (slot (make-instance 'foo
)) 1))
52 (assert-error (eval '(setf (slot (make-instance 'foo
)) t
))
54 (eval '(succeed/sv
(make-instance 'foo
)))
55 (assert-error (eval '(fail/sv
(make-instance 'foo
)))
57 (eval '(succeed/acc
(make-instance 'foo
)))
58 (assert-error (eval '(fail/acc
(make-instance 'foo
)))
60 (eval '(make-instance 'foo
:slot
1))
61 (assert-error (eval '(make-instance 'foo
:slot t
))
63 (eval '(make-instance 'foo
:slot
*one
*))
64 (assert-error (eval '(make-instance 'foo
:slot
*t
*))
67 (with-test (:name
(:evaluator
/gf
))
68 (eval '(setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) 1))
70 (eval '(setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) t
))
72 (eval '(setf (slot/gf
(make-instance 'foo
/gf
)) 1))
73 (assert-error (eval '(setf (slot/gf
(make-instance 'foo
/gf
)) t
))
75 (eval '(succeed/sv
/gf
(make-instance 'foo
/gf
)))
76 (assert-error (eval '(fail/sv
/gf
(make-instance 'foo
/gf
)))
78 (eval '(succeed/acc
/gf
(make-instance 'foo
/gf
)))
79 (assert-error (eval '(fail/acc
/gf
(make-instance 'foo
/gf
)))
81 (eval '(make-instance 'foo
/gf
:slot
/gf
1))
82 (assert-error (eval '(make-instance 'foo
/gf
:slot
/gf t
))
84 (eval '(make-instance 'foo
/gf
:slot
/gf
*one
*))
85 (assert-error (eval '(make-instance 'foo
/gf
:slot
/gf
*t
*))
89 (with-test (:name
(:compiler
))
90 (funcall (compile nil
'(lambda ()
91 (setf (slot-value (make-instance 'foo
) 'slot
) 1))))
92 (funcall (compile nil
'(lambda () (setf (slot (make-instance 'foo
)) 1))))
95 (compile nil
'(lambda () (setf (slot (make-instance 'foo
)) t
))))
97 (funcall (compile nil
'(lambda () (succeed/sv
(make-instance 'foo
)))))
99 (funcall (compile nil
'(lambda () (fail/sv
(make-instance 'foo
)))))
101 (funcall (compile nil
'(lambda () (succeed/acc
(make-instance 'foo
)))))
103 (funcall (compile nil
'(lambda () (fail/acc
(make-instance 'foo
)))))
105 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
1))))
107 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot t
))))
109 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
*one
*))))
111 (funcall (compile nil
'(lambda () (make-instance 'foo
:slot
*t
*))))
114 (with-test (:name
(:compiler
:setf
:slot-value
))
117 (compile nil
'(lambda ()
118 (setf (slot-value (make-instance 'foo
) 'slot
) t
))))
122 (with-test (:name
(:compiler
/gf
))
123 (funcall (compile nil
125 (setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) 1))))
126 (funcall (compile nil
'(lambda () (setf (slot/gf
(make-instance 'foo
/gf
)) 1))))
130 '(lambda () (setf (slot/gf
(make-instance 'foo
/gf
)) t
))))
132 (funcall (compile nil
'(lambda () (succeed/sv
/gf
(make-instance 'foo
/gf
)))))
134 (funcall (compile nil
'(lambda ()
135 (fail/sv
/gf
(make-instance 'foo
/gf
)))))
137 (funcall (compile nil
'(lambda () (succeed/acc
/gf
(make-instance 'foo
/gf
)))))
139 (funcall (compile nil
'(lambda ()
140 (fail/acc
/gf
(make-instance 'foo
/gf
)))))
142 (funcall (compile nil
'(lambda () (make-instance 'foo
/gf
:slot
/gf
1))))
144 (funcall (compile nil
'(lambda ()
145 (make-instance 'foo
/gf
:slot
/gf t
))))
147 (funcall (compile nil
'(lambda () (make-instance 'foo
/gf
:slot
/gf
*one
*))))
149 (funcall (compile nil
'(lambda ()
150 (make-instance 'foo
/gf
:slot
/gf
*t
*))))
153 (with-test (:name
(:compiler
/gf
:setf
:slot-value
))
158 (setf (slot-value (make-instance 'foo
/gf
) 'slot
/gf
) t
))))
162 (with-test (:name
(:slot-inheritance
:slot-value
:float
/single-float
))
163 (defclass a
() ((slot1 :initform
0.0 :type float
)))
164 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
165 (defmethod inheritance-test ((a a
)) (setf (slot-value a
'slot1
) 1d0
))
166 (inheritance-test (make-instance 'a
))
167 (assert-error (inheritance-test (make-instance 'b
)) type-error
))
169 (with-test (:name
(:slot-inheritance
:slot-value
:t
/single-float
))
170 (defclass a
() ((slot1 :initform
0.0)))
171 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
172 (defmethod inheritance-test ((a a
)) (setf (slot-value a
'slot1
) 1d0
))
173 (inheritance-test (make-instance 'a
))
174 (assert-error (inheritance-test (make-instance 'b
)) type-error
))
176 (with-test (:name
(:slot-inheritance
:writer
:float
/single-float
))
177 (defclass a
() ((slot1 :initform
0.0 :type float
:accessor slot1-of
)))
178 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
179 (defmethod inheritance-test ((a a
)) (setf (slot1-of a
) 1d0
))
180 (inheritance-test (make-instance 'a
))
181 (assert-error (inheritance-test (make-instance 'b
)) type-error
))
183 (with-test (:name
(:slot-inheritance
:writer
:float
/single-float
))
184 (defclass a
() ((slot1 :initform
0.0 :accessor slot1-of
)))
185 (defclass b
(a) ((slot1 :initform
0.0 :type single-float
)))
186 (defmethod inheritance-test ((a a
)) (setf (slot1-of a
) 1d0
))
187 (inheritance-test (make-instance 'a
))
188 (assert-error (inheritance-test (make-instance 'b
)) type-error
))
190 (with-test (:name
(:slot-inheritance
:type-intersection
))
200 :type unsigned-byte
)))
203 (setf (slot1-of (make-instance 'a
*)) -
1)
204 (setf (slot1-of (make-instance 'b
*)) (1+ most-positive-fixnum
))
205 (setf (slot1-of (make-instance 'c
*)) 1)
206 (assert-error (setf (slot1-of (make-instance 'c
*)) -
1)
208 (assert-error (setf (slot1-of (make-instance 'c
*))
209 (1+ most-positive-fixnum
))
211 (assert-error (make-instance 'c
* :slot1 -
1)
213 (assert-error (make-instance 'c
* :slot1
(1+ most-positive-fixnum
))
217 ((slot1 :initform nil
220 :type
(or null function
))))
222 ((slot1 :initform nil
225 :type
(or null
(function (fixnum) fixnum
)))))
227 (with-test (:name
(:type
:function
))
228 (setf (slot1-of (make-instance 'a
)) (lambda () 1))
229 (setf (slot1-of (make-instance 'b
)) (lambda () 1))
230 (assert-error (setf (slot1-of (make-instance 'a
)) 1)
232 (assert-error (setf (slot1-of (make-instance 'b
)) 1)
234 (make-instance 'a
:slot1
(lambda () 1))
235 (make-instance 'b
:slot1
(lambda () 1)))
237 (with-test (:name
:alternate-metaclass
/standard-instance-structure-protocol
)
238 (defclass my-alt-metaclass
(standard-class) ())
239 (defmethod sb-mop:validate-superclass
((class my-alt-metaclass
) superclass
)
241 (defclass my-alt-metaclass-instance-class
()
242 ((slot :type fixnum
:initarg
:slot
))
243 (:metaclass my-alt-metaclass
))
244 (defun make-my-instance (class)
245 (make-instance class
:slot
:not-a-fixnum
))
246 (assert-error (make-my-instance 'my-alt-metaclass-instance-class
)
249 (with-test (:name
:typecheck-class-allocation
)
250 ;; :CLASS slot :INITFORMs are executed at class definition time
252 (eval `(locally (declare (optimize safety
))
253 (defclass class-allocation-test-bad
()
254 ((slot :initform
"slot"
257 :allocation
:class
)))))
259 (let ((name (gensym "CLASS-ALLOCATION-TEST-GOOD")))
260 (eval `(locally (declare (optimize safety
))
262 ((slot :initarg
:slot
263 :type
(integer 100 200)
264 :allocation
:class
)))))
266 `(macrolet ((check (form)
267 `(assert (multiple-value-bind (ok err
)
268 (ignore-errors ,form
)
270 (typep err
'type-error
)
271 (equal '(integer 100 200)
272 (type-error-expected-type err
)))))))
273 (macrolet ((test (form)
275 (check (eval '(locally (declare (optimize safety
))
277 (check (funcall (compile nil
'(lambda ()
278 (declare (optimize safety
))
280 (test-slot (value form
)
282 (assert (eql ,value
(slot-value (eval ',form
) 'slot
)))
283 (assert (eql ,value
(slot-value (funcall (compile nil
'(lambda () ,form
)))
285 (test (make-instance ',name
:slot
:bad
))
286 (assert (not (slot-boundp (make-instance ',name
) 'slot
)))
287 (let ((* (make-instance ',name
:slot
101)))
289 (test (setf (slot-value * 'slot
) (list 1 2 3)))
290 (setf (slot-value * 'slot
) 110)
292 (test-slot 110 (make-instance ',name
))
293 (test-slot 111 (make-instance ',name
:slot
111)))))))