Fix defmethod arglists leaking into make-method-lambda.
authorStas Boukarev <stassats@gmail.com>
Thu, 31 Oct 2013 14:47:09 +0000 (18:47 +0400)
committerStas Boukarev <stassats@gmail.com>
Thu, 31 Oct 2013 14:48:26 +0000 (18:48 +0400)
defmethod communicates to make-method-lambda using special variables,
but make-method-lambda then performs code-walking which expands
macros, and if a macro calls another make-method-lambda directly, this
make-method-lambda will receive incorrect information which may cause
problems with wrong lambda lists.
Reported and diagnosed by Attila Lendvai.

src/pcl/boot.lisp
tests/clos.impure.lisp

index e470eb4..2e558ff 100644 (file)
@@ -588,8 +588,13 @@ bootstrapping.
     ;; if there is are no non-standard prior MAKE-METHOD-LAMBDA methods -- or
     ;; unless they're fantastically unintrusive.
     (let* ((method-name *method-name*)
+           (method-lambda-list *method-lambda-list*)
+           ;; Macroexpansion caused by code-walking may call make-method-lambda and
+           ;; end up with wrong values
+           (*method-name* nil)
+           (*method-lambda-list* nil)
            (generic-function-name (when method-name (car method-name)))
-           (specialized-lambda-list (or *method-lambda-list*
+           (specialized-lambda-list (or method-lambda-list
                                         (ecase (car method-lambda)
                                           (lambda (second method-lambda))
                                           (named-lambda (third method-lambda)))))
index 2113f59..7864721 100644 (file)
   (defmethod sb-mop:validate-superclass ((x bug-309076-class) (y standard-class)) t)
   (assert (typep (make-instance 'bug-309076-class) 'bug-309076-class)))
 
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require 'sb-cltl2)
+  (defmethod b ()))
+
+(defmacro macro ()
+  (let ((a 20))
+    (declare (special a))
+    (assert
+     (=
+      (funcall
+       (compile nil
+                (sb-mop:make-method-lambda
+                 #'b
+                 (find-method #'b () ())
+                 '(lambda () (declare (special a)) a)
+                 nil))
+       '(1) ())
+      20))))
+
+(with-test (:name :make-method-lambda-leakage)
+  ;; lambda list of X leaks into the invocation of make-method-lambda
+  ;; during code-walking performed by make-method-lambda invoked by
+  ;; DEFMETHOD
+  (sb-cltl2:macroexpand-all '(defmethod x (a) (macro))))
+
+
 ;;;; success