GNU bug report logs - #4845
23.1.50; Uninterned symbols in .elc files

Previous Next

Package: emacs;

Reported by: Helmut Eller <eller.helmut <at> gmail.com>

Date: Sun, 1 Nov 2009 10:00:03 UTC

Severity: normal

Done: Stefan Kangas <stefan <at> marxist.se>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: John Wiegley <jwiegley <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: Marcin Borkowski <mbork <at> amu.edu.pl>, 4845 <at> debbugs.gnu.org, Helmut Eller <eller.helmut <at> gmail.com>
Subject: bug#4845: 23.1.50; Uninterned symbols in .elc files
Date: Tue, 19 Jan 2016 09:26:14 -0800
[Message part 1 (text/plain, inline)]
>>>>> Alan Mackenzie <acm <at> muc.de> writes:

>>> (defmacro foo ()
>>> (let ((sym (make-symbol "bar")))
>>> `(progn
>>> (defun ,sym () (message "function %s called" ',sym))
>>> (,sym))))
>>> 
>>> (foo)

>>> However loading the corresponding compiled file signals an error:

shell> emacs -Q -batch -eval '(byte-compile-file "x.el")' -load x.elc
>>> Wrote /tmp/x.elc
>>> Symbol's function definition is void: bar

This example becomes clearer if we use `gensym' instead of `make-symbol
"bar"`.  Here is a macro expansion:

Byte-compiled:

  (progn
    (defun bar68503 nil
      (message "function %s called" '#:bar68503))
    (#:bar68503))

Interpreted:

  (progn
    (defun bar68503 nil
      (message "function %s called" 'bar68503))
    (bar68503))

What's happening here is this:

  1. At compile-time, we're creating a new, uninterned symbol, and we are
     both passing that symbol to defun, and calling it.

  2. `defun', at compilation time, is using the _name_ of that symbol to
     define a function definition for an interned symbol of the same name.

  3. We then try to print and call the uninterned symbol directly. So what we
     are calling, and what defun defined, are not the same symbol.

This works when non-byte-compiled because we don't inline the symbol
reference, making it a reference by name instead of by value. You can trigger
the same error behavior at interpretation time with:

  (defmacro foo ()
    (let ((sym (gensym)))
      `(progn
         (defun ,sym () (message "function %s called" ',sym))
         (funcall (symbol-function (quote ,sym))))))
  
  (foo)

I don't think this is a bug, rather macro expansion doing exactly what it was
told to do. If anything, it's odd that when interpreting, we expand to a
reference by name; but I suppose that makes sense too, given the more dynamic
nature of interpreted code.

The general rule to follow is: Don't leak internal symbols. If you use
`gensym' or `make-symbol', ensure that all dependencies on that symbol occur
entirely within the macro body. `defun' is used to establish global
definitions, so it effectively "exports" the internal symbol, breaking the
abstraction. That it has inconsistent behavior here is due to differences in
the way that byte-compilation inlines references.

I recommend closure of this bug as expected behavior, unless there are further
concerns.

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2
[signature.asc (application/pgp-signature, inline)]

This bug report was last modified 4 years and 186 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.