teach NODE-CONSERVATIVE-TYPE about union types
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 7 Oct 2012 11:12:59 +0000 (14:12 +0300)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 7 Oct 2012 11:48:33 +0000 (14:48 +0300)
  Conservative type of STRING is STRING -- and this makes it so.

  Fixes lp#1050768 (but also future-proof ARRAY-IN-BOUNDS-P against
  '*) explicitly.

NEWS
src/compiler/array-tran.lisp
src/compiler/ir1opt.lisp
tests/compiler.pure.lisp

diff --git a/NEWS b/NEWS
index 29bfc32..9057028 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ changes relative to sbcl-1.1.0:
     (thanks to SANO Masatoshi)
   * bug fix: PARSE-NATIVE-NAMESTRING performed non-native parsing when
     :JUNK-ALLOWED was true.
+  * bug fix: type derivation inferred overly conservative types for
+    unions of array types. (lp#1050768)
 
 changes in sbcl-1.1.0 relative to sbcl-1.0.58:
   * enhancement: New variable, sb-ext:*disassemble-annotate* for controlling
index 0cf9279..baf1b98 100644 (file)
     (block nil
       (let ((dimensions (array-type-dimensions-or-give-up
                          (lvar-conservative-type array))))
+        ;; Might be *. (Note: currently this is never true, because the type
+        ;; derivation infers the rank from the call to ARRAY-IN-BOUNDS-P, but
+        ;; let's keep this future proof.)
+        (when (eq '* dimensions)
+          (give-up-ir1-transform "array bounds unknown"))
         ;; shortcut for zero dimensions
         (when (some (lambda (dim)
                       (and (bound-known-p dim) (zerop dim)))
index 7d4fdd2..dc6769b 100644 (file)
               :specialized-element-type (array-type-specialized-element-type type))
              ;; Simple arrays cannot change at all.
              type))
+        ((union-type-p type)
+         ;; Conservative union type is an union of conservative types.
+         (let ((res *empty-type*))
+           (dolist (part (union-type-types type) res)
+             (setf res (type-union res (conservative-type part))))))
         (t
+         ;; Catch-all.
+         ;;
          ;; If the type contains some CONS types, the conservative type contains all
          ;; of them.
          (when (types-equal-or-intersect type (specifier-type 'cons))
index 85d4d1c..7d8faf1 100644 (file)
                                 (cons (or (car x) (meh)))
                                 (t (meh)))))))
                    (funcall (eh x)))) t t)))
+
+(with-test (:name (:bug-1050768 :symptom))
+  ;; Used to signal an error.
+  (compile nil
+           `(lambda (string position)
+              (char string position)
+              (array-in-bounds-p string (1+ position)))))
+
+(with-test (:name (:bug-1050768 :cause))
+  (let ((types `((string string)
+                 ((or (simple-array character 24) (vector t 24))
+                  (or (simple-array character 24) (vector t))))))
+    (dolist (pair types)
+      (destructuring-bind (orig conservative) pair
+        (assert sb-c::(type= (specifier-type cl-user::conservative)
+                             (conservative-type (specifier-type cl-user::orig))))))))