0.8.0.46:
authorChristophe Rhodes <csr21@cam.ac.uk>
Sat, 7 Jun 2003 16:37:23 +0000 (16:37 +0000)
committerChristophe Rhodes <csr21@cam.ac.uk>
Sat, 7 Jun 2003 16:37:23 +0000 (16:37 +0000)
Fix for argumentless CALL-NEXT-METHOD and assignment
... and a simple test.

NEWS
src/pcl/boot.lisp
tests/clos.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index fb5f80e..12168c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1815,6 +1815,11 @@ changes in sbcl-0.8.1 relative to sbcl-0.8.0:
        causes a type error.
     ** (SETF FIND-CLASS) now accepts NIL as an argument to remove the
        association between the name and a class.
+    ** generic functions with non-standard method-combination and over
+       six methods all of which return constants no longer return NIL
+       after the first few invocations.  (thanks to Gerd Moellmann)
+    ** CALL-NEXT-METHOD with no arguments now passes the original
+       values of the arguments, even in the presence of assignment.
 
 planned incompatible changes in 0.8.x:
   * (not done yet, but planned:) When the profiling interface settles
index 8577b76..ab5388d 100644 (file)
@@ -804,22 +804,25 @@ bootstrapping.
 (defmacro bind-simple-lexical-method-macros ((method-args next-methods)
                                             &body body)
   `(macrolet ((call-next-method-bind (&body body)
-               `(let ((.next-method. (car ,',next-methods))
-                      (,',next-methods (cdr ,',next-methods)))
-                  .next-method. ,',next-methods
-                  ,@body))
+              `(let ((.next-method. (car ,',next-methods))
+                     (,',next-methods (cdr ,',next-methods)))
+                .next-method. ,',next-methods
+                ,@body))
              (call-next-method-body (method-name-declaration cnm-args)
-               `(if .next-method.
-                    (funcall (if (std-instance-p .next-method.)
-                                 (method-function .next-method.)
-                                 .next-method.) ; for early methods
-                             (or ,cnm-args ,',method-args)
-                             ,',next-methods)
-                    (apply #'call-no-next-method ',method-name-declaration
+              `(if .next-method.
+                   (funcall (if (std-instance-p .next-method.)
+                                (method-function .next-method.)
+                            .next-method.) ; for early methods
+                            (or ,cnm-args ,',method-args)
+                            ,',next-methods)
+                   (apply #'call-no-next-method ',method-name-declaration
                            (or ,cnm-args ,',method-args))))
              (next-method-p-body ()
-               `(not (null .next-method.))))
-     ,@body))
+              `(not (null .next-method.)))
+             (with-rebound-original-args ((call-next-method-p) &body body)
+               (declare (ignore call-next-method-p))
+               `(let () ,@body)))
+    ,@body))
 
 (defun call-no-next-method (method-name-declaration &rest args)
   (destructuring-bind (name) method-name-declaration
@@ -1037,85 +1040,93 @@ bootstrapping.
 \f
 (defmacro bind-fast-lexical-method-macros ((args rest-arg next-method-call)
                                           &body body)
-  `(macrolet ((narrowed-emf (emf)
-               ;; INVOKE-EFFECTIVE-METHOD-FUNCTION has code in it to
-               ;; dispatch on the possibility that EMF might be of
-               ;; type FIXNUM (as an optimized representation of a
-               ;; slot accessor). But as far as I (WHN 2002-06-11)
-               ;; can tell, it's impossible for such a representation
-               ;; to end up as .NEXT-METHOD-CALL. By reassuring
-               ;; INVOKE-E-M-F that when called from this context
-               ;; it needn't worry about the FIXNUM case, we can
-               ;; keep those cases from being compiled, which is
-               ;; good both because it saves bytes and because it
-               ;; avoids annoying type mismatch compiler warnings.
-               ;;
-                ;; KLUDGE: In sbcl-0.7.4.29, the compiler's type
-               ;; system isn't smart enough about NOT and intersection
-               ;; types to benefit from a (NOT FIXNUM) declaration
-               ;; here. -- WHN 2002-06-12
-               ;;
-               ;; FIXME: Might the FUNCTION type be omittable here,
-               ;; leaving only METHOD-CALLs? Failing that, could this
-               ;; be documented somehow? (It'd be nice if the types
-               ;; involved could be understood without solving the
-                ;; halting problem.)
-                `(the (or function method-call fast-method-call)
+  (let* ((all-params (append args (when rest-arg (list rest-arg))))
+        (rebindings (mapcar (lambda (x) (list x x)) all-params)))
+    `(macrolet ((narrowed-emf (emf)
+                ;; INVOKE-EFFECTIVE-METHOD-FUNCTION has code in it to
+                ;; dispatch on the possibility that EMF might be of
+                ;; type FIXNUM (as an optimized representation of a
+                ;; slot accessor). But as far as I (WHN 2002-06-11)
+                ;; can tell, it's impossible for such a representation
+                ;; to end up as .NEXT-METHOD-CALL. By reassuring
+                ;; INVOKE-E-M-F that when called from this context
+                ;; it needn't worry about the FIXNUM case, we can
+                ;; keep those cases from being compiled, which is
+                ;; good both because it saves bytes and because it
+                ;; avoids annoying type mismatch compiler warnings.
+                ;;
+                ;; KLUDGE: In sbcl-0.7.4.29, the compiler's type
+                ;; system isn't smart enough about NOT and
+                ;; intersection types to benefit from a (NOT FIXNUM)
+                ;; declaration here. -- WHN 2002-06-12 (FIXME: maybe
+                ;; it is now... -- CSR, 2003-06-07)
+                ;;
+                ;; FIXME: Might the FUNCTION type be omittable here,
+                ;; leaving only METHOD-CALLs? Failing that, could this
+                ;; be documented somehow? (It'd be nice if the types
+                ;; involved could be understood without solving the
+                ;; halting problem.)
+                `(the (or function method-call fast-method-call)
                   ,emf))
-             (call-next-method-bind (&body body)
-               `(let () ,@body))
-             (call-next-method-body (method-name-declaration cnm-args)
-               `(if ,',next-method-call
-                 ,(locally
-                   ;; This declaration suppresses a "deleting
-                   ;; unreachable code" note for the following IF when
-                   ;; REST-ARG is NIL. It is not nice for debugging
-                   ;; SBCL itself, but at least it keeps us from
-                   ;; annoying users.
-                   (declare (optimize (inhibit-warnings 3)))
-                   (if (and (null ',rest-arg)
-                            (consp cnm-args)
-                            (eq (car cnm-args) 'list))
-                       `(invoke-effective-method-function
-                         (narrowed-emf ,',next-method-call)
-                        nil
-                         ,@(cdr cnm-args))
-                       (let ((call `(invoke-effective-method-function
-                                     (narrowed-emf ,',next-method-call)
-                                     ,',(not (null rest-arg))
-                                     ,@',args
-                                     ,@',(when rest-arg `(,rest-arg)))))
-                         `(if ,cnm-args
-                           (bind-args ((,@',args
-                                        ,@',(when rest-arg
-                                             `(&rest ,rest-arg)))
-                                       ,cnm-args)
-                            ,call)
-                           ,call))))
-                ,(locally
-                  ;; As above, this declaration suppresses code
-                  ;; deletion notes.
-                  (declare (optimize (inhibit-warnings 3)))
-                  (if (and (null ',rest-arg)
-                           (consp cnm-args)
-                           (eq (car cnm-args) 'list))
-                      `(call-no-next-method ',method-name-declaration
-                                            ,@(cdr cnm-args))
-                      `(call-no-next-method ',method-name-declaration
-                                            ,@',args
-                                            ,@',(when rest-arg
-                                                      `(,rest-arg)))))))
-             (next-method-p-body ()
-               `(not (null ,',next-method-call))))
-    ,@body))
+               (call-next-method-bind (&body body)
+                `(let () ,@body))
+               (call-next-method-body (method-name-declaration cnm-args)
+                `(if ,',next-method-call
+                     ,(locally
+                       ;; This declaration suppresses a "deleting
+                       ;; unreachable code" note for the following IF
+                       ;; when REST-ARG is NIL. It is not nice for
+                       ;; debugging SBCL itself, but at least it
+                       ;; keeps us from annoying users.
+                       (declare (optimize (inhibit-warnings 3)))
+                       (if (and (null ',rest-arg)
+                                (consp cnm-args)
+                                (eq (car cnm-args) 'list))
+                           `(invoke-effective-method-function
+                             (narrowed-emf ,',next-method-call)
+                             nil
+                             ,@(cdr cnm-args))
+                           (let ((call `(invoke-effective-method-function
+                                         (narrowed-emf ,',next-method-call)
+                                         ,',(not (null rest-arg))
+                                         ,@',args
+                                         ,@',(when rest-arg `(,rest-arg)))))
+                             `(if ,cnm-args
+                               (bind-args ((,@',args
+                                            ,@',(when rest-arg
+                                                      `(&rest ,rest-arg)))
+                                           ,cnm-args)
+                                ,call)
+                               ,call))))
+                     ,(locally
+                       ;; As above, this declaration suppresses code
+                       ;; deletion notes.
+                       (declare (optimize (inhibit-warnings 3)))
+                       (if (and (null ',rest-arg)
+                                (consp cnm-args)
+                                (eq (car cnm-args) 'list))
+                           `(call-no-next-method ',method-name-declaration
+                             ,@(cdr cnm-args))
+                           `(call-no-next-method ',method-name-declaration
+                             ,@',args
+                             ,@',(when rest-arg
+                                       `(,rest-arg)))))))
+               (next-method-p-body ()
+                `(not (null ,',next-method-call)))
+               (with-rebound-original-args ((cnm-p) &body body)
+                 (if cnm-p
+                     `(let ,',rebindings
+                       (declare (ignorable ,@',all-params))
+                       ,@body)
+                     `(let () ,@body))))
+      ,@body)))
 
 (defmacro bind-lexical-method-functions
     ((&key call-next-method-p next-method-p-p
           closurep applyp method-name-declaration)
      &body body)
   (cond ((and (null call-next-method-p) (null next-method-p-p)
-             (null closurep)
-             (null applyp))
+             (null closurep) (null applyp))
         `(let () ,@body))
        (t
         `(call-next-method-bind
@@ -1126,8 +1137,9 @@ bootstrapping.
                              cnm-args))))
                   ,@(and next-method-p-p
                          '((next-method-p ()
-                             (next-method-p-body)))))
-             ,@body)))))
+                            (next-method-p-body)))))
+             (with-rebound-original-args (,call-next-method-p)
+               ,@body))))))
 
 (defmacro bind-args ((lambda-list args) &body body)
   (let ((args-tail '.args-tail.)
index ec1f012..014fa2f 100644 (file)
 (assert (equal (cpl (make-broadcast-stream))
               '(broadcast-stream stream structure-object)))
 \f
+;;; Bug in CALL-NEXT-METHOD: assignment to the method's formal
+;;; parameters shouldn't affect the arguments to the next method for a
+;;; no-argument call to CALL-NEXT-METHOD
+(defgeneric cnm-assignment (x)
+  (:method (x) x)
+  (:method ((x integer)) (setq x 3)
+          (list x (call-next-method) (call-next-method x))))
+(assert (equal (cnm-assignment 1) '(3 1 3)))
+\f
 ;;;; success
 (sb-ext:quit :unix-status 104)
index 6715542..e471612 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.0.45"
+"0.8.0.46"