fixes in EXPT type derivation
authorChristophe Rhodes <csr21@cantab.net>
Mon, 3 Jun 2013 13:54:17 +0000 (14:54 +0100)
committerChristophe Rhodes <csr21@cantab.net>
Mon, 3 Jun 2013 13:56:15 +0000 (14:56 +0100)
It was possible to construct mostly (but not completely) unobservable
bogus floating-point types when deriving the type of functions
returning the value of calls to EXPT.  Noticed by Vsevolod Dyomkin,
who found a way to observe it by redefining methods.

NEWS
src/compiler/float-tran.lisp
tests/compiler.impure.lisp

diff --git a/NEWS b/NEWS
index 0bcf148..36c42df 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ changes relative to sbcl-1.1.8:
   * optimization: when referencing internal functions as #'x, don't go through
     an indirect fdefn structure.
   * optimization: SLEEP doesn't cons on non-immediate floats and on ratios.
+  * bug fix: EXPT type derivation no longer constructs bogus floating-point
+    types.  (reported by Vsevolod Dyomkin)
   
 changes in sbcl-1.1.8 relative to sbcl-1.1.7:
   * notice: The implementation of MAP-ALLOCATED-OBJECTS (the heart of
index 1877cef..51cf1dd 100644 (file)
                                 (single-float ,f-lo, f-hi)))))
            (float
             ;; A positive integer to a float power is a float.
-            (modified-numeric-type y-type
-                                   :low (interval-low bnd)
-                                   :high (interval-high bnd)))
+            (let ((format (numeric-type-format y-type)))
+              (aver format)
+              (modified-numeric-type
+               y-type
+               :low (coerce-numeric-bound (interval-low bnd) format)
+               :high (coerce-numeric-bound (interval-high bnd) format))))
            (t
             ;; A positive integer to a number is a number (for now).
             (specifier-type 'number))))
                                 (single-float ,f-lo, f-hi)))))
            (float
             ;; A positive rational to a float power is a float.
-            (modified-numeric-type y-type
-                                   :low (interval-low bnd)
-                                   :high (interval-high bnd)))
+            (let ((format (numeric-type-format y-type)))
+              (aver format)
+              (modified-numeric-type
+               y-type
+               :low (coerce-numeric-bound (interval-low bnd) format)
+               :high (coerce-numeric-bound (interval-high bnd) format))))
            (t
             ;; A positive rational to a number is a number (for now).
             (specifier-type 'number))))
            ((or integer rational)
             ;; A positive float to an integer or rational power is
             ;; always a float.
-            (make-numeric-type
-             :class 'float
-             :format (numeric-type-format x-type)
-             :low (interval-low bnd)
-             :high (interval-high bnd)))
+            (let ((format (numeric-type-format x-type)))
+              (aver format)
+              (make-numeric-type
+               :class 'float
+               :format format
+               :low (coerce-numeric-bound (interval-low bnd) format)
+               :high (coerce-numeric-bound (interval-high bnd) format))))
            (float
             ;; A positive float to a float power is a float of the
             ;; higher type.
-            (make-numeric-type
-             :class 'float
-             :format (float-format-max (numeric-type-format x-type)
-                                       (numeric-type-format y-type))
-             :low (interval-low bnd)
-             :high (interval-high bnd)))
+            (let ((format (float-format-max (numeric-type-format x-type)
+                                            (numeric-type-format y-type))))
+              (aver format)
+              (make-numeric-type
+               :class 'float
+               :format format
+               :low (coerce-numeric-bound (interval-low bnd) format)
+               :high (coerce-numeric-bound (interval-high bnd) format))))
            (t
             ;; A positive float to a number is a number (for now)
             (specifier-type 'number))))
index 29eb6c3..fe4f6c3 100644 (file)
                    (call-1035721 #'identity-1035721)
                    (lambda (x)
                      (identity-1035721 x))))))
+
+(test-util:with-test (:name :expt-type-derivation-and-method-redefinition)
+  (defmethod expt-type-derivation ((x list) &optional (y 0.0))
+    (declare (type float y))
+    (expt 2 y))
+  ;; the redefinition triggers a type lookup of the old
+  ;; fast-method-function's type, which had a bogus type specifier of
+  ;; the form (double-float 0) from EXPT type derivation
+  (defmethod expt-type-derivation ((x list) &optional (y 0.0))
+    (declare (type float y))
+    (expt 2 y)))
 ;;; success