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.
;; 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)))))
(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