# HG changeset patch # User Aidan Kehoe # Date 1315753505 -3600 # Node ID 6c76f5b7e2e3e77d6a7c4a21507032a2adae439e # Parent d19b6e3bdf91e4e1f99857e9973c86fa2bebb40c Be more careful still in #'cl-defsubst-expand. lisp/ChangeLog addition: 2011-09-11 Aidan Kehoe * cl-macs.el (cl-defsubst-expand): Be more careful still here, make sure that any references to variables in BODY don't access those values in the enclosing scope when that would be inappropriate. Add some documentation of a potential reasonable approach to avoiding the problems with our (non-Common Lisp-conformant) #'symbol-macrolet. diff -r d19b6e3bdf91 -r 6c76f5b7e2e3 lisp/ChangeLog --- a/lisp/ChangeLog Sat Sep 10 13:17:29 2011 +0100 +++ b/lisp/ChangeLog Sun Sep 11 16:05:05 2011 +0100 @@ -1,3 +1,13 @@ +2011-09-11 Aidan Kehoe + + * cl-macs.el (cl-defsubst-expand): + Be more careful still here, make sure that any references to + variables in BODY don't access those values in the enclosing scope + when that would be inappropriate. + Add some documentation of a potential reasonable approach to + avoiding the problems with our (non-Common Lisp-conformant) + #'symbol-macrolet. + 2011-09-10 Aidan Kehoe * cl-macs.el (cl-defsubst-expand): diff -r d19b6e3bdf91 -r 6c76f5b7e2e3 lisp/cl-macs.el --- a/lisp/cl-macs.el Sat Sep 10 13:17:29 2011 +0100 +++ b/lisp/cl-macs.el Sun Sep 11 16:05:05 2011 +0100 @@ -3238,18 +3238,25 @@ (if (or simple (cl-const-expr-p argv)) (progn ;; Avoid infinite loop on symbol macro - ;; expansion, make sure none of the argvs - ;; refer to the symbols in the argns. + ;; expansion: (or (block find - ;; Can't use cl-expr-contains, that - ;; doesn't descend lambdas: - (subst nil argn argvs :test - #'(lambda (elt tree) + (subst nil argn argvs :test + #'(lambda (elt tree) + ;; Give nil if argn is + ;; in argvs somewhere: (if (eq elt tree) - (return-from find t)))) - nil) - (push (list argn argv) symbol-macros)) - (and unsafe (list (list argn argv)))) + (return-from find))))) + (let ((copy-symbol (copy-symbol argn))) + ;; Rename ARGN within BODY so it + ;; doesn't conflict with its value + ;; in the including scope: + (setq body + (cl-macroexpand-all + body `((,(eq-hash argn) + ,copy-symbol))) + argn copy-symbol))) + (push (list argn argv) symbol-macros) + (and unsafe (list (list argn argv)))) (list (list argn argv)))) argns argvs))) `(let ,lets @@ -3260,6 +3267,13 @@ ;; bound). We don't have GNU's issue where the replacement will ;; be done when the symbol is used in a function context, ;; because we're using #'symbol-macrolet instead of #'subst. + ;; + ;; #'symbol-macrolet as specified by Common Lisp is shadowed by + ;; #'let, #'let* and lambda argument lists, and that would suit + ;; our purposes here perfectly; we could implement it in + ;; cl-macroexpand-all by shadowing any existing symbol macros + ;; when we descend let forms or arglist lambdas. Doing it + ;; unconditionally could well break #'loop, though. ,symbol-macros ,body)))))