0.7.7.19:
authorWilliam Harold Newman <william.newman@airmail.net>
Mon, 9 Sep 2002 01:09:15 +0000 (01:09 +0000)
committerWilliam Harold Newman <william.newman@airmail.net>
Mon, 9 Sep 2002 01:09:15 +0000 (01:09 +0000)
corrected BUGS 35 entry as per APD sbcl-devel 2002-08-07
merged APD "more strict type checking" patch (sbcl-devel
2002-08-08), fixing bug 192a ("free type declarations
are promises") and one of the problems lumped into
bug 194 (the case of type checking getting lost
when THE occurs inside MULTIPLE-VALUE-PROG1)

BUGS
NEWS
src/compiler/ir1-translators.lisp
src/compiler/ir1tran.lisp
src/compiler/macros.lisp
tests/compiler.impure.lisp
tests/dump.impure-cload.lisp
version.lisp-expr

diff --git a/BUGS b/BUGS
index 12a9426..a4cf1a8 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -1,4 +1,4 @@
-tREPORTING BUGS
+REPORTING BUGS
 
 Bugs can be reported on the help mailing list
   sbcl-help@lists.sourceforge.net
@@ -183,7 +183,8 @@ WORKAROUND:
   then executing
     (FOO 1.5)
   will cause the INTEGERP case to be selected, giving bogus output a la
-    exactly 1.33..
+    exactly 2.5
+  (or (FOO 1000.5), "exactly 1001.5")
   This violates the "declarations are assertions" principle.
   According to the ANSI spec, in the section "System Class FUNCTION",
   this is a case of "lying to the compiler", but the lying is done
@@ -1280,17 +1281,9 @@ WORKAROUND:
      lists and &KEY arguments) do not signal errors when they should.
 
 192: "Python treats free type declarations as promises."
-  a. original report by Alexey Dejneka (on sbcl-devel 2002-08-26):
-       (declaim (optimize (speed 0) (safety 3)))
-       (defun f (x)
-         (declare (real x))
-         (+ x
-            (locally (declare (single-float x))
-            (sin x))))
-     Now (F NIL) correctly gives a type error, but (F 100) gives
-     a segmentation violation.
-  b. same fundamental problem in a different way, easy to stumble
-     across if you mistype and declare the wrong index in
+  b. What seemed like the same fundamental problem as bug 192a, but
+     was not fixed by the same (APD "more strict type checking
+     sbcl-devel 2002-08-97) patch:
      (DOTIMES (I ...) (DOTIMES (J ...) (DECLARE ...) ...)):
        (declaim (optimize (speed 1) (safety 3)))
        (defun trust-assertion (i)
@@ -1320,8 +1313,31 @@ WORKAROUND:
   bad argument value is).
 
 194: "no error from (THE REAL '(1 2 3)) in some cases"
-  (Actually this entry is probably two separate bugs, as
-  Alexey Dejneka commented on sbcl-devel 2002-09-03:)
+  fixed parts:
+    a. In sbcl-0.7.7.9, 
+         (multiple-value-prog1 (progn (the real '(1 2 3))))
+       returns (1 2 3) instead of signalling an error. This was fixed by 
+       APD's "more strict type checking patch", but although the fixed
+       code (in sbcl-0.7.7.19) works (signals TYPE-ERROR) interactively,
+       it's difficult to write a regression test for it, because 
+       (IGNORE-ERRORS (MULTIPLE-VALUE-PROG1 (PROGN (THE REAL '(1 2 3)))))
+       still returns (1 2 3).
+  still-broken parts:  
+    b. (IGNORE-ERRORS (MULTIPLE-VALUE-PROG1 (PROGN (THE REAL '(1 2 3)))))    
+       returns (1 2 3). (As above, this shows up when writing regression
+       tests for fixed-ness of part a.)
+    c. Also in sbcl-0.7.7.9, (IGNORE-ERRORS (THE REAL '(1 2 3))) => (1 2 3).
+    d. At the REPL,
+         (null (ignore-errors
+           (let ((arg1 1)
+                 (arg2 (identity (the real #(1 2 3)))))
+             (if (< arg1 arg2) arg1 arg2))))
+           => T
+      but putting the same expression inside (DEFUN FOO () ...),
+      (FOO) => NIL.
+  notes:
+    * Actually this entry is probably multiple bugs, as
+      Alexey Dejneka commented on sbcl-devel 2002-09-03:)
        I don't think that placing these two bugs in one entry is
        a good idea: they have different explanations. The second
        (min 1 nil) is caused by flushing of unused code--IDENTITY
@@ -1330,35 +1346,12 @@ WORKAROUND:
        for the result, it forgets about type assertion. The purpose
        of IDENTITY is to save the restricted continuation from
        inaccurate transformations.
-  In sbcl-0.7.7.9, 
-    (multiple-value-prog1 (progn (the real '(1 2 3))))
-  returns (1 2 3) instead of signalling an error. Also in sbcl-0.7.7.9,
-  a more complicated instance of this bug kept 
-  (IGNORE-ERRORS (MIN '(1 2 3))) from returning NIL as it should when
-  the MIN source transform expanded to (THE REAL '(1 2 3)), because
-  (IGNORE-ERRORS (THE REAL '(1 2 3))) returns (1 2 3).
-  Alexey Dejneka pointed out that
-  (IGNORE-ERRORS (IDENTITY (THE REAL '(1 2 3)))) works as it should.
-  (IGNORE-ERRORS (VALUES (THE REAL '(1 2 3)))) also works as it should.
-  Perhaps this is another case of VALUES type intersections behaving
-  in non-useful ways?
-    When I (WHN) tried to use the VALUES trick to work around this bug
-  in the MIN source transform, it didn't work for
-    (assert (null (ignore-errors (min 1 #(1 2 3)))))
-  Hand-expanding the source transform, I get
-    (assert (null (ignore-errors
-                   (let ((arg1 1)
-                         (arg2 (identity (the real #(1 2 3)))))
-                     (if (< arg1 arg2) arg1 arg2))))) 
-  which fails (i.e. the assertion fails, because the IGNORE-ERRORS
-  doesn't report MIN signalling a type error). At the REPL
-    (null (ignore-errors
-           (let ((arg1 1)
-                 (arg2 (identity (the real #(1 2 3)))))
-             (if (< arg1 arg2) arg1 arg2))))
-    => T
-  but when this expression is used as the body of (DEFUN FOO () ...)
-  then (FOO)=>NIL.
+    * Alexey Dejneka pointed out that
+       (IGNORE-ERRORS (IDENTITY (THE REAL '(1 2 3))))
+      works as it should. Also
+       (IGNORE-ERRORS (VALUES (THE REAL '(1 2 3))))
+      works as it should. Perhaps this is another case of VALUES type
+      intersections behaving in non-useful ways?
 
 195: "confusing reporting of not-a-REAL TYPE-ERRORs from THE REAL"
   In sbcl-0.7.7.10, (THE REAL #(1 2 3)) signals a type error which
diff --git a/NEWS b/NEWS
index 59bd7fb..08a464c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1263,6 +1263,9 @@ changes in sbcl-0.7.8 relative to sbcl-0.7.7:
     found).
   * fixed bug 174: FORMAT's error message is slightly clearer when a
     non-printing character is used in a format directive.
+  * fixed several bugs in compiler checking of type declarations, i.e.
+    violations of the Python "declarations are assertions" principle
+    (thanks to Alexey Dejneka)
 
 planned incompatible changes in 0.7.x:
 * When the profiling interface settles down, maybe in 0.7.x, maybe
index 809d384..cb8e3a3 100644 (file)
 ;;; We make this work by getting USE-CONTINUATION to do the unioning
 ;;; across COND branches. We can't do it here, since we don't know how
 ;;; many branches there are going to be.
-(defun ir1ize-the-or-values (type cont lexenv name)
+(defun ir1ize-the-or-values (type cont lexenv place)
   (declare (type continuation cont) (type lexenv lexenv))
-  (let* ((ctype (values-specifier-type type))
+  (let* ((ctype (if (typep type 'ctype) type (values-specifier-type type)))
         (old-type (or (lexenv-find cont type-restrictions)
                       *wild-type*))
         (intersects (values-types-equal-or-intersect old-type ctype))
               (not (policy *lexenv*
                            (= inhibit-warnings 3)))) ;FIXME: really OK to suppress?
       (compiler-warn
-       "The type ~S in ~S declaration conflicts with an ~
+       "The type ~S ~A conflicts with an ~
         enclosing assertion:~%   ~S"
        (type-specifier ctype)
-       name
+       place
        (type-specifier old-type)))
     (make-lexenv :type-restrictions `((,cont . ,new))
                 :default lexenv)))
 ;;; this didn't seem to expand into an assertion, at least for ALIEN
 ;;; values. Check that SBCL doesn't have this problem.
 (def-ir1-translator the ((type value) start cont)
-  (let ((*lexenv* (ir1ize-the-or-values type cont *lexenv* 'the)))
+  (with-continuation-type-assertion (cont (values-specifier-type type)
+                                          "in THE declaration")
     (ir1-convert start cont value)))
 
 ;;; This is like the THE special form, except that it believes
     (continuation-starts-block dummy-start)
     (ir1-convert start dummy-start result)
 
-    (substitute-continuation-uses cont dummy-start)
+    (with-continuation-type-assertion
+        (cont (continuation-asserted-type dummy-start)
+              "of the first form")
+      (substitute-continuation-uses cont dummy-start))
 
     (continuation-starts-block dummy-result)
     (ir1-convert-progn-body dummy-start dummy-result forms)
index b5ad3de..8f392dc 100644 (file)
 ;;; functional instead.
 (defun reference-leaf (start cont leaf)
   (declare (type continuation start cont) (type leaf leaf))
-  (let* ((leaf (or (and (defined-fun-p leaf)
-                       (not (eq (defined-fun-inlinep leaf)
-                                :notinline))
-                       (let ((functional (defined-fun-functional leaf)))
-                         (when (and functional
-                                    (not (functional-kind functional)))
-                           (maybe-reanalyze-functional functional))))
-                  leaf))
-        (res (make-ref (or (lexenv-find leaf type-restrictions)
-                           (leaf-type leaf))
-                       leaf)))
-    (push res (leaf-refs leaf))
-    (setf (leaf-ever-used leaf) t)
-    (link-node-to-previous-continuation res start)
-    (use-continuation res cont)))
+  (with-continuation-type-assertion
+      (cont (or (lexenv-find leaf type-restrictions) *wild-type*)
+            "in DECLARE")
+    (let* ((leaf (or (and (defined-fun-p leaf)
+                          (not (eq (defined-fun-inlinep leaf)
+                                   :notinline))
+                          (let ((functional (defined-fun-functional leaf)))
+                            (when (and functional
+                                       (not (functional-kind functional)))
+                              (maybe-reanalyze-functional functional))))
+                     leaf))
+           (res (make-ref (leaf-type leaf)
+                          leaf)))
+      (push res (leaf-refs leaf))
+      (setf (leaf-ever-used leaf) t)
+      (link-node-to-previous-continuation res start)
+      (use-continuation res cont))))
 
 ;;; Convert a reference to a symbolic constant or variable. If the
 ;;; symbol is entered in the LEXENV-VARS we use that definition,
                                       `(values ,@types))
                                   cont
                                   res
-                                  'values))))
+                                  "in VALUES declaration"))))
       (dynamic-extent
        (when (policy *lexenv* (> speed inhibit-warnings))
         (compiler-note
index 3ea38a5..0a5d134 100644 (file)
     `(if ,n-res
         (values (cdr ,n-res) t)
         (values nil nil))))
+
+;;;
+(defmacro with-continuation-type-assertion ((cont ctype context) &body body)
+  `(let ((*lexenv* (ir1ize-the-or-values ,ctype ,cont *lexenv* ,context)))
+     ,@body))
 \f
 ;;;; the EVENT statistics/trace utility
 
index 63273bf..72013e8 100644 (file)
            ;; Uncomment and it works
            ))
     (eff)))
+
+;;; bug 192a, fixed by APD "more strict type checking" patch
+;;; (sbcl-devel 2002-08-07)
+(defun bug192a (x)
+  (declare (optimize (speed 0) (safety 3)))
+  ;; Even with bug 192a, this declaration was checked as an assertion.
+  (declare (real x))
+  (+ x
+     (locally
+       ;; Because of bug 192a, this declaration was trusted without checking.
+       (declare (single-float x))
+       (sin x))))
+(assert (null (ignore-errors (bug192a nil))))
+(multiple-value-bind (result error) (ignore-errors (bug192a 100))
+  (assert (null result))
+  (assert (equal (type-error-expected-type error) 'single-float)))
+
+;;; bug 194, fixed in part by APD "more strict type checking" patch
+;;; (sbcl-devel 2002-08-07)
+(progn
+  #+nil ; FIXME: still broken in 0.7.7.19 (after patch)
+  (multiple-value-bind (result error)
+      (ignore-errors (multiple-value-prog1 (progn (the real '(1 2 3)))))
+    (assert (null result))
+    (assert (typep error 'type-error)))
+  #+nil ; FIXME: still broken in 0.7.7.19 (after patch)
+  (multiple-value-bind (result error)
+      (ignore-errors (the real '(1 2 3)))
+    (assert (null result))
+    (assert (typep error 'type-error))))
 \f
 ;;; BUG 48a. and b. (symbol-macrolet handling), fixed by Eric Marsden
 ;;; and Raymond Toy for CMUCL, fix ported for sbcl-0.7.6.18.
     (compile nil '(lambda () (symbol-macrolet ((t nil)) t)))
   (assert failure-p)
   (assert (raises-error? (funcall function) program-error)))
-
 (multiple-value-bind (function warnings-p failure-p)
-    (compile nil '(lambda () (symbol-macrolet ((*standard-input* nil)) *standard-input*)))
+    (compile nil
+            '(lambda ()
+               (symbol-macrolet ((*standard-input* nil))
+                 *standard-input*)))
   (assert failure-p)
   (assert (raises-error? (funcall function) program-error)))
 #||
index 614e5c7..5a468f2 100644 (file)
@@ -28,7 +28,7 @@
   (declare (type list keys))
   (loop
       for c in '#1=("Red" "Blue" . #1#)
-      for key in keys ))
+      for key in keys))
 
 ;;; sbcl-0.6.11.25 or so had DEF!STRUCT/MAKE-LOAD-FORM/HOST screwed up
 ;;; so that the compiler couldn't dump pathnames.
index 7739f33..6a310bc 100644 (file)
@@ -18,4 +18,4 @@
 ;;; for internal versions, especially for internal versions off the
 ;;; main CVS branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
 
-"0.7.7.18"
+"0.7.7.19"