0.7.10.10:
[sbcl.git] / tests / compiler.impure.lisp
index e8572ce..9a8458c 100644 (file)
@@ -348,6 +348,293 @@ BUG 48c, not yet fixed:
   (assert (null v))
   (assert (typep e 'type-error)))
 (assert (equal (exercise-0-7-7-24-bug -4) '(3f0 3f0)))
+
+;;; non-intersecting type declarations were DWIMing in a confusing
+;;; fashion until sbcl-0.7.7.28, when APD reported and fixed the
+;;; problem.
+(defun non-intersecting-the (x)
+  (let (y)
+    (setf y (the single-float (the integer x)))
+    (list y y)))
+
+(raises-error? (foo 3) type-error)
+(raises-error? (foo 3f0) type-error)
+
+;;; until 0.8.2 SBCL did not check THEs in arguments
+(defun the-in-arguments-aux (x)
+  x)
+(defun the-in-arguments-1 (x)
+  (list x (the-in-arguments-aux (the (single-float 0s0) x))))
+(defun the-in-arguments-2 (x)
+  (list x (the-in-arguments-aux (the single-float x))))
+
+(multiple-value-bind (result condition)
+    (ignore-errors (the-in-arguments-1 1))
+  (assert (null result))
+  (assert (typep condition 'type-error)))
+(multiple-value-bind (result condition)
+    (ignore-errors (the-in-arguments-2 1))
+  (assert (null result))
+  (assert (typep condition 'type-error)))
+
+;;; bug 153: a hole in a structure slot type checking
+(declaim (optimize safety))
+(defstruct foo153
+  (bla 0 :type fixnum))
+(defun bug153-1 ()
+  (let ((foo (make-foo153)))
+    (setf (foo153-bla foo) '(1 . 1))
+    (format t "Is ~a of type ~a a cons? => ~a~%"
+            (foo153-bla foo)
+            (type-of (foo153-bla foo))
+            (consp (foo153-bla foo)))))
+(defun bug153-2 (x)
+  (let ((foo (make-foo153)))
+    (setf (foo153-bla foo) x)
+    (format t "Is ~a of type ~a a cons? => ~a~%"
+            (foo153-bla foo)
+            (type-of (foo153-bla foo))
+            (consp (foo153-bla foo)))))
+
+(multiple-value-bind (result condition)
+    (ignore-errors (bug153-1))
+  (declare (ignore result))
+  (assert (typep condition 'type-error)))
+(multiple-value-bind (result condition)
+    (ignore-errors (bug153-2 '(1 . 1)))
+  (declare (ignore result))
+  (assert (typep condition 'type-error)))
+
+;;; bug 110: the compiler flushed the argument type test and the default
+;;; case in the cond.
+
+(defun bug110 (x)
+  (declare (optimize (safety 2) (speed 3)))
+  (declare (type (or string stream) x))
+  (cond ((typep x 'string) 'string)
+        ((typep x 'stream) 'stream)
+        (t
+         'none)))
+
+(multiple-value-bind (result condition)
+    (ignore-errors (bug110 0))
+  (declare (ignore result))
+  (assert (typep condition 'type-error)))
+
+;;; bug 202: the compiler failed to compile a function, which derived
+;;; type contradicted declared.
+(declaim (ftype (function () null) bug202))
+(defun bug202 ()
+  t)
+
+;;; bugs 178, 199: compiler failed to compile a call of a function
+;;; with a hairy type
+(defun bug178 (x)
+      (funcall (the function (the standard-object x))))
+
+(defun bug199-aux (f)
+  (eq nil (funcall f)))
+
+(defun bug199 (f x)
+  (declare (type (and function (satisfies bug199-aux)) f))
+  (funcall f x))
+
+;;; check non-toplevel DEFMACRO
+(defvar *defmacro-test-status* nil)
+
+(defun defmacro-test ()
+  (fmakunbound 'defmacro-test-aux)
+  (let* ((src "defmacro-test.lisp")
+         (obj (compile-file-pathname src)))
+    (unwind-protect
+         (progn
+           (compile-file src)
+           (assert (equal *defmacro-test-status* '(function a)))
+           (setq *defmacro-test-status* nil)
+           (load obj)
+           (assert (equal *defmacro-test-status* nil))
+           (macroexpand '(defmacro-test-aux 'a))
+           (assert (equal *defmacro-test-status* '(macro 'a z-value)))
+           (eval '(defmacro-test-aux 'a))
+           (assert (equal *defmacro-test-status* '(expanded 'a z-value))))
+      (ignore-errors (delete-file obj)))))
+
+(defmacro-test)
+
+;;; bug 204: EVAL-WHEN inside a local environment
+(defvar *bug204-test-status*)
+
+(defun bug204-test ()
+  (let* ((src "bug204-test.lisp")
+         (obj (compile-file-pathname src)))
+    (unwind-protect
+         (progn
+           (setq *bug204-test-status* nil)
+           (compile-file src)
+           (assert (equal *bug204-test-status* '((:expanded :load-toplevel)
+                                                 (:called :compile-toplevel)
+                                                 (:expanded :compile-toplevel))))
+           (setq *bug204-test-status* nil)
+           (load obj)
+           (assert (equal *bug204-test-status* '((:called :load-toplevel)))))
+      (ignore-errors (delete-file obj)))))
+
+(bug204-test)
+
+;;; toplevel SYMBOL-MACROLET
+(defvar *symbol-macrolet-test-status*)
+
+(defun symbol-macrolet-test ()
+  (let* ((src "symbol-macrolet-test.lisp")
+         (obj (compile-file-pathname src)))
+    (unwind-protect
+         (progn
+           (setq *symbol-macrolet-test-status* nil)
+           (compile-file src)
+           (assert (equal *symbol-macrolet-test-status*
+                          '(2 1)))
+           (setq *symbol-macrolet-test-status* nil)
+           (load obj)
+           (assert (equal *symbol-macrolet-test-status* '(2))))
+      (ignore-errors (delete-file obj)))))
+
+(symbol-macrolet-test)
+
+;;; On the x86, this code failed to compile until sbcl-0.7.8.37:
+(defun x86-assembler-failure (x)
+  (declare (optimize (speed 3) (safety 0)))
+  (eq (setf (car x) 'a) nil))
+
+;;; bug 211: :ALLOW-OTHER-KEYS
+(defun bug211d (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
+  (list x x-p y y-p))
+
+(assert (equal (bug211d) '(:x nil :y nil)))
+(assert (equal (bug211d :x 1) '(1 t :y nil)))
+(assert (raises-error? (bug211d :y 2) program-error))
+(assert (equal (bug211d :y 2 :allow-other-keys t :allow-other-keys nil)
+               '(:x nil t t)))
+(assert (raises-error? (bug211d :y 2 :allow-other-keys nil) program-error))
+
+(let ((failure-p
+       (nth-value
+        3
+        (compile 'bug211b
+                 '(lambda ()
+                   (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
+                            (list x x-p y y-p)))
+                     (assert (equal (test) '(:x nil :y nil)))
+                     (assert (equal (test :x 1) '(1 t :y nil)))
+                     (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
+                                    '(:x nil 11 t)))))))))
+  (assert (not failure-p))
+  (bug211b))
+
+(let ((failure-p
+       (nth-value
+        3
+        (compile 'bug211c
+                 '(lambda ()
+                   (flet ((test (&key (x :x x-p))
+                            (list x x-p)))
+                     (assert (equal (test) '(:x nil)))
+                     (assert (equal (test :x 1) '(1 t)))
+                     (assert (equal (test :y 2 :allow-other-keys 11 :allow-other-keys nil)
+                                    '(:x nil)))))))))
+  (assert (not failure-p))
+  (bug211c))
+
+(dolist (form '((test :y 2)
+                (test :y 2 :allow-other-keys nil)
+                (test :y 2 :allow-other-keys nil :allow-other-keys t)))
+  (multiple-value-bind (result warnings-p failure-p)
+      (compile nil `(lambda ()
+                     (flet ((test (&key (x :x x-p) ((:allow-other-keys y) :y y-p))
+                              (list x x-p y y-p)))
+                       ,form)))
+    (assert failure-p)
+    (assert (raises-error? (funcall result) program-error))))
+
+;;; bug 217: wrong type inference
+(defun bug217-1 (x s)
+  (let ((f (etypecase x
+             (character #'write-char)
+             (integer #'write-byte))))
+    (funcall f x s)
+    (etypecase x
+      (character (write-char x s))
+      (integer (write-byte x s)))))
+(bug217-1 #\1 *standard-output*)
+
+
+;;; bug 221: tried and died on CSUBTYPEP (not VALUES-SUBTYPEP) of the
+;;; function return types when inferring the type of the IF expression
+(declaim (ftype (function (fixnum) (values package boolean)) bug221f1))
+(declaim (ftype (function (t) (values package boolean)) bug221f2))
+(defun bug221 (b x)
+  (funcall (if b #'bug221f1 #'bug221f2) x))
+\f
+;;; bug 172: macro lambda lists were too permissive until 0.7.9.28
+;;; (fix provided by Matthew Danish) on sbcl-devel
+(assert (null (ignore-errors
+               (defmacro bug172 (&rest rest foo) `(list ,rest ,foo)))))
+
+;;; embedded THEs
+(defun check-embedded-thes (policy1 policy2 x y)
+  (handler-case
+      (funcall (compile nil
+                        `(lambda (f)
+                           (declare (optimize (speed 2) (safety ,policy1)))
+                           (multiple-value-list
+                            (the (values (integer 2 3) t)
+                              (locally (declare (optimize (safety ,policy2)))
+                                (the (values t (single-float 2f0 3f0))
+                                  (funcall f)))))))
+               (lambda () (values x y)))
+    (type-error (error)
+      error)))
+
+(assert (equal (check-embedded-thes 0 0  :a :b) '(:a :b)))
+
+(assert (equal (check-embedded-thes 0 3  :a 2.5f0) '(:a 2.5f0)))
+(assert (typep (check-embedded-thes 0 3  2 3.5f0) 'type-error))
+
+(assert (equal (check-embedded-thes 0 1  :a 3.5f0) '(:a 3.5f0)))
+(assert (typep (check-embedded-thes 0 1  2 2.5d0) 'type-error))
+
+#+nil
+(assert (equal (check-embedded-thes 3 0  2 :a) '(2 :a)))
+(assert (typep (check-embedded-thes 3 0  4 2.5f0) 'type-error))
+
+(assert (equal (check-embedded-thes 1 0  4 :b) '(4 :b)))
+(assert (typep (check-embedded-thes 1 0  1.0 2.5f0) 'type-error))
+
+
+(assert (equal (check-embedded-thes 3 3  2 2.5f0) '(2 2.5f0)))
+(assert (typep (check-embedded-thes 3 3  0 2.5f0) 'type-error))
+(assert (typep (check-embedded-thes 3 3  2 3.5f0) 'type-error))
+
+\f
+;;; INLINE inside MACROLET
+(declaim (inline to-be-inlined))
+(macrolet ((def (x) `(defun ,x (y) (+ y 1))))
+  (def to-be-inlined))
+(defun call-inlined (z)
+  (to-be-inlined z))
+(assert (= (call-inlined 3) 4))
+(macrolet ((frob (x) `(+ ,x 3)))
+  (defun to-be-inlined (y)
+    (frob y)))
+(assert (= (call-inlined 3)
+          ;; we should have inlined the previous definition, so the
+          ;; new one won't show up yet.
+          4))
+(defun call-inlined (z)
+  (to-be-inlined z))
+(assert (= (call-inlined 3) 6))
+(defun to-be-inlined (y)
+  (+ y 5))
+(assert (= (call-inlined 3) 6))
 \f
 ;;;; tests not in the problem domain, but of the consistency of the
 ;;;; compiler machinery itself