From a189a69454ef7635149319ae213b337f17c50d20 Mon Sep 17 00:00:00 2001 From: Stas Boukarev Date: Fri, 3 Jan 2014 18:03:21 +0400 Subject: [PATCH] UPGRADED-ARRAY-ELEMENT-TYPE: more thoroughly signal errors on unknown types. 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 | 24 +++++++++++++++++++----- tests/compiler.pure.lisp | 4 ++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/compiler/generic/vm-type.lisp b/src/compiler/generic/vm-type.lisp index d5750cd..9d0a031 100644 --- a/src/compiler/generic/vm-type.lisp +++ b/src/compiler/generic/vm-type.lisp @@ -107,6 +107,13 @@ (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 @@ -120,7 +127,7 @@ ;; 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*) @@ -140,10 +147,17 @@ "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 diff --git a/tests/compiler.pure.lisp b/tests/compiler.pure.lisp index f20d6f5..1fd9166 100644 --- a/tests/compiler.pure.lisp +++ b/tests/compiler.pure.lisp @@ -4970,3 +4970,7 @@ (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)))) -- 1.7.10.4