From fb91e1987cc40f3f698f2972d0de50426ec3086f Mon Sep 17 00:00:00 2001 From: William Harold Newman Date: Mon, 9 Sep 2002 01:09:15 +0000 Subject: [PATCH] 0.7.7.19: 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 | 81 +++++++++++++++++-------------------- NEWS | 3 ++ src/compiler/ir1-translators.lisp | 16 +++++--- src/compiler/ir1tran.lisp | 34 ++++++++-------- src/compiler/macros.lisp | 5 +++ tests/compiler.impure.lisp | 36 ++++++++++++++++- tests/dump.impure-cload.lisp | 2 +- version.lisp-expr | 2 +- 8 files changed, 109 insertions(+), 70 deletions(-) diff --git a/BUGS b/BUGS index 12a9426..a4cf1a8 100644 --- 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 --- 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 diff --git a/src/compiler/ir1-translators.lisp b/src/compiler/ir1-translators.lisp index 809d384..cb8e3a3 100644 --- a/src/compiler/ir1-translators.lisp +++ b/src/compiler/ir1-translators.lisp @@ -718,9 +718,9 @@ ;;; 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)) @@ -734,10 +734,10 @@ (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))) @@ -749,7 +749,8 @@ ;;; 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 @@ -1011,7 +1012,10 @@ (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) diff --git a/src/compiler/ir1tran.lisp b/src/compiler/ir1tran.lisp index b5ad3de..8f392dc 100644 --- a/src/compiler/ir1tran.lisp +++ b/src/compiler/ir1tran.lisp @@ -544,21 +544,23 @@ ;;; 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, @@ -1115,7 +1117,7 @@ `(values ,@types)) cont res - 'values)))) + "in VALUES declaration")))) (dynamic-extent (when (policy *lexenv* (> speed inhibit-warnings)) (compiler-note diff --git a/src/compiler/macros.lisp b/src/compiler/macros.lisp index 3ea38a5..0a5d134 100644 --- a/src/compiler/macros.lisp +++ b/src/compiler/macros.lisp @@ -709,6 +709,11 @@ `(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)) ;;;; the EVENT statistics/trace utility diff --git a/tests/compiler.impure.lisp b/tests/compiler.impure.lisp index 63273bf..72013e8 100644 --- a/tests/compiler.impure.lisp +++ b/tests/compiler.impure.lisp @@ -269,6 +269,36 @@ ;; 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)))) ;;; BUG 48a. and b. (symbol-macrolet handling), fixed by Eric Marsden ;;; and Raymond Toy for CMUCL, fix ported for sbcl-0.7.6.18. @@ -276,9 +306,11 @@ (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))) #|| diff --git a/tests/dump.impure-cload.lisp b/tests/dump.impure-cload.lisp index 614e5c7..5a468f2 100644 --- a/tests/dump.impure-cload.lisp +++ b/tests/dump.impure-cload.lisp @@ -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. diff --git a/version.lisp-expr b/version.lisp-expr index 7739f33..6a310bc 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 1.7.10.4