UPGRADED-ARRAY-ELEMENT-TYPE: more thoroughly signal errors on unknown types.
authorStas Boukarev <stassats@gmail.com>
Fri, 3 Jan 2014 14:03:21 +0000 (18:03 +0400)
committerStas Boukarev <stassats@gmail.com>
Fri, 3 Jan 2014 14:03:21 +0000 (18:03 +0400)
Intersection and union types containing unknown types were handled incorrectly.
(upgraded-array-element-type '(and fixnum unknown)) => was FIXNUM.

src/compiler/generic/vm-type.lisp
tests/compiler.pure.lisp

index d5750cd..9d0a031 100644 (file)
     (double-float 'double-float)
     #!+long-float (long-float 'long-float)))
 
+(defun contains-unknown-type-p (ctype)
+  (cond ((unknown-type-p ctype) t)
+        ((intersection-type-p ctype)
+         (some #'contains-unknown-type-p (intersection-type-types ctype)))
+        ((union-type-p ctype)
+         (some #'contains-unknown-type-p (union-type-types ctype)))))
+
 ;;; This function is called when the type code wants to find out how
 ;;; an array will actually be implemented. We set the
 ;;; SPECIALIZED-ELEMENT-TYPE to correspond to the actual
                   ;; assuming that the upgraded-element-type should be
                   ;; equal to T, given the way that the AREF
                   ;; DERIVE-TYPE optimizer works.  -- CSR, 2002-08-19
-                  (unknown-type-p eltype))
+                  (contains-unknown-type-p eltype))
               *wild-type*
               (dolist (stype-name *specialized-array-element-types*
                                   *universal-type*)
   "Return the element type that will actually be used to implement an array
    with the specifier :ELEMENT-TYPE Spec."
   (declare (ignore environment))
-  (if (unknown-type-p (specifier-type spec))
-      (error "undefined type: ~S" spec)
-      (type-specifier (array-type-specialized-element-type
-                       (specifier-type `(array ,spec))))))
+  (handler-case
+      ;; Can't rely on SPECIFIER-TYPE to signal PARSE-UNKNOWN-TYPE in
+      ;; the case of (AND KNOWN UNKNOWN), since the result of the
+      ;; outter call to SPECIFIER-TYPE can be cached by the code that
+      ;; doesn't catch PARSE-UNKNOWN-TYPE signal.
+      (if (contains-unknown-type-p (specifier-type spec))
+          (error "Undefined type: ~S" spec)
+          (type-specifier (array-type-specialized-element-type
+                           (specifier-type `(array ,spec)))))
+    (parse-unknown-type (c)
+      (error "Undefined type: ~S" (parse-unknown-type-specifier c)))))
 
 (defun sb!xc:upgraded-complex-part-type (spec &optional environment)
   #!+sb-doc
index f20d6f5..1fd9166 100644 (file)
                      (when (= (array-rank a) 3)
                        (array-dimension a 2)))))))
     (assert noted)))
+
+(with-test (:name :upgraded-array-element-type-undefined-type)
+  (raises-error? (upgraded-array-element-type 'an-undefined-type))
+  (raises-error? (upgraded-array-element-type '(and fixnum an-undefined-type))))