Hi all,
I've been experiencing some strange bugs related to the slime-show-xrefs function trying to access the 'void variable' package. This behavior occurs more or less consistently while editing (on a Linux machine) a set of files that where written using the Franz Emacs Lisp Interface on a MacOSX.
Here is one example of the stacktrace:
Debugger entered--Lisp error: (void-variable package) (slime-init-xref-buffer package G88189 G88190) (progn (slime-init-xref-buffer package G88189 G88190) (make-local-variable (quote slime-xref-saved-window-configuration)) (setq slime-xref-saved-window-configuration (current-window-configuration))) (prog2 (progn (slime-init-xref-buffer package G88189 G88190) (make-local-variable ...) (setq slime-xref-saved-window-configuration ...)) (progn (slime-insert-xrefs xrefs) (goto-char ...) (forward-line) (skip-chars-forward " ")) (setq buffer-read-only t) (select-window (or ... ...)) (shrink-window-if-larger-than-buffer)) (save-current-buffer (set-buffer (get-buffer-create ...)) (prog2 (progn ... ... ...) (progn ... ... ... ...) (setq buffer-read-only t) (select-window ...) (shrink-window-if-larger-than-buffer))) (with-current-buffer (get-buffer-create (format "*XREF[%s: %s]*" G88189 G88190)) (prog2 (progn ... ... ...) (progn ... ... ... ...) (setq buffer-read-only t) (select-window ...) (shrink-window-if-larger-than-buffer))) (let ((G88189 type) (G88190 symbol)) (with-current-buffer (get-buffer-create ...) (prog2 ... ... ... ... ...))) (slime-with-xref-buffer (package type symbol) (slime-insert-xrefs xrefs) (goto-char (point-min)) (forward-line) (skip-chars-forward " ")) (if (null xrefs) (message "No references found for %s." symbol) (setq slime-next-location-function (quote slime-goto-next-xref)) (slime-with-xref-buffer (package type symbol) (slime-insert-xrefs xrefs) (goto-char ...) (forward-line) (skip-chars-forward " "))) slime-show-xrefs((("expression-right-operand" ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INFIX-EXPRESSION)))" :location ... ... nil) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INSTANCEOF-EXPRESSION)))" :location ... ... nil) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND :AROUND (NODE)))" :location ... ... nil) ("(:OPERATOR EXPRESSION-RIGHT-OPERAND)" :location ... ... nil))) definition "expression-right-operand" ":jnil") slime-show-definitions("expression-right-operand" (("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INFIX-EXPRESSION)))" (:location ... ... nil)) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INSTANCEOF-EXPRESSION)))" (:location ... ... nil)) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND :AROUND (NODE)))" (:location ... ... nil)) ("(:OPERATOR EXPRESSION-RIGHT-OPERAND)" (:location ... ... nil)))) (if (slime-length> definitions 1) (slime-show-definitions name definitions) (let (...) (destructure-case ... ... ...))) slime-goto-definition("expression-right-operand" (("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INFIX-EXPRESSION)))" (:location ... ... nil)) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND (INSTANCEOF-EXPRESSION)))" (:location ... ... nil)) ("(:OPERATOR (METHOD EXPRESSION-RIGHT-OPERAND :AROUND (NODE)))" (:location ... ... nil)) ("(:OPERATOR EXPRESSION-RIGHT-OPERAND)" (:location ... ... nil))) nil) (if (null definitions) (if slime-edit-definition-fallback-function (funcall slime-edit-definition-fallback-function name) (error "No known definition for: %s" name)) (slime-goto-definition name definitions where)) (let ((definitions ...)) (if (null definitions) (if slime-edit-definition-fallback-function ... ...) (slime-goto-definition name definitions where))) slime-edit-definition("expression-right-operand") call-interactively(slime-edit-definition)
Here is (what I think is) the relevant function:
(defun slime-show-xrefs (xrefs type symbol package) "Show the results of an XREF query." (if (null xrefs) (message "No references found for %s." symbol) (setq slime-next-location-function 'slime-goto-next-xref) (slime-with-xref-buffer (package type symbol) (slime-insert-xrefs xrefs) (goto-char (point-min)) (forward-line) (skip-chars-forward " \t"))))
This function uses the macro slime-with-xref-buffer:
(defmacro* slime-with-xref-buffer ((package ref-type symbol) &body body) "Execute BODY in a xref buffer, then show that buffer." (let ((type (gensym)) (sym (gensym))) `(let ((,type ,ref-type) (,sym ,symbol)) (with-current-buffer (get-buffer-create (format "*XREF[%s: %s]*" ,type ,sym)) (prog2 (progn (slime-init-xref-buffer ,package ,type ,sym) (make-local-variable 'slime-xref-saved-window-configuration) (setq slime-xref-saved-window-configuration (current-window-configuration))) (progn ,@body) (setq buffer-read-only t) (select-window (or (get-buffer-window (current-buffer) t) (display-buffer (current-buffer) t))) (shrink-window-if-larger-than-buffer))))))
I confess that I couldn't identify the cause for the bug. However, I noticed that the macrocall expands into a
(with-current-buffer ... (slime-init-xref-buffer package ...))
and maybe it was that 'package' variable being referenced after changing to a different buffer that was causing the problem. An hard to believe explanation, I'm sure, but just in case, I experimented replacing that 'package' variable by another gensym, using:
(defmacro* slime-with-xref-buffer ((package ref-type symbol) &body body) "Execute BODY in a xref buffer, then show that buffer." (let ((type (gensym)) (sym (gensym)) (pkg (gensym))) `(let ((,type ,ref-type) (,sym ,symbol) (,pkg ,package)) (with-current-buffer (get-buffer-create (format "*XREF[%s: %s]*" ,type ,sym)) (prog2 (progn (slime-init-xref-buffer ,pkg ,type ,sym) (make-local-variable 'slime-xref-saved-window-configuration) (setq slime-xref-saved-window-configuration (current-window-configuration))) (progn ,@body) (setq buffer-read-only t) (select-window (or (get-buffer-window (current-buffer) t) (display-buffer (current-buffer) t))) (shrink-window-if-larger-than-buffer))))))
and after redefining slime-show-xrefs, everything worked OK.
Maybe a Slime expert can understand the problem.
Best regards,
António Leitão.
Antonio Menezes Leitao aml@gia.ist.utl.pt writes:
and maybe it was that 'package' variable being referenced after changing to a different buffer that was causing the problem. An hard to believe explanation, I'm sure, but just in case, I experimented replacing that 'package' variable by another gensym, using:
I can believe that. The reason for problems like this are those -*- package: ... -*- file variables. This make package a buffer local variable in Emacs and interacts badly dynamic bindings. E.g.:
(progn (make-variable-buffer-local 'my-var) (setq my-var 1) (message "%s" my-var) (let ((my-var 2)) (message "%s" my-var) (with-temp-buffer (message "%s" my-var))))
my-var in the temp buffer is nil. One would think that a simple rule like: first search let-bound variables, then buffer local variables and then global variables would avoid such problems but this is obviously not what Emacs does.
It's probably a good idea to avoid the -*- package: ... -*- thing as the file has probably a in-package form already or a least rename it to Package.
I committed you change. Thanks.
Helmut.
Hi,
Helmut Eller heller@common-lisp.net writes:
Antonio Menezes Leitao aml@gia.ist.utl.pt writes:
and maybe it was that 'package' variable being referenced after changing to a different buffer that was causing the problem. An hard to believe explanation, I'm sure, but just in case, I experimented replacing that 'package' variable by another gensym, using:
I can believe that. The reason for problems like this are those -*- package: ... -*- file variables. This make package a buffer local variable in Emacs and interacts badly dynamic bindings. E.g.:
(progn (make-variable-buffer-local 'my-var) (setq my-var 1) (message "%s" my-var) (let ((my-var 2)) (message "%s" my-var) (with-temp-buffer (message "%s" my-var))))
my-var in the temp buffer is nil. One would think that a simple rule like: first search let-bound variables, then buffer local variables and then global variables would avoid such problems but this is obviously not what Emacs does.
It's probably a good idea to avoid the -*- package: ... -*- thing as the file has probably a in-package form already or a least rename it to Package.
I committed you change. Thanks.
Here's another one that is causing problems:
(defun slime-repl-set-package (package) "Set the package of the REPL buffer to PACKAGE." (interactive (list (slime-read-package-name "Package: " (slime-find-buffer-package)))) (with-current-buffer (slime-output-buffer) (let ((unfinished-input (slime-repl-current-input))) (destructuring-bind (name prompt-string) (slime-eval `(swank:set-package ,package)) (setf (slime-lisp-package) name) (setf (slime-lisp-package-prompt-string) prompt-string) (slime-repl-insert-prompt "" 0) (insert unfinished-input)))))
Again, using pkg in place of package solves the problem but, as you explained, the problem seems to be on Emacs and not on Slime.
Thanks for the explanation.
António Leitão.