Subject: Re: bug#27016: possible bug in `defsetf'

From: Michael Heerdegen <[email-masked]>
Date: Tue, 23 May 2017 01:10:09 +0200

[email-masked] writes:

> Oh, right, I see it now.  It happens in 24.4 and later.  I'm not sure
> it's a bug though.  My guess is that the difference is eager
> macroexpansion.  When I compile, then I get the same behaviour with 24.3
> (that's my earliest working Emacs build) as well.

(require 'cl)

(macroexpand-1 (macroexpand-1 (macroexpand-1 '(defsetf foobar setcar))))
==>

#+begin_src emacs-lisp
(gv-define-expander foobar
  (lambda
    (do &rest args)
    (gv--defsetter 'foobar
                   (lambda
                     (val &rest args)
                     `(,'setcar ,@args ,val))
                   do args)))
#+end_src

A comment in the definition of `gv-define-expander' says:

  ;; Use eval-and-compile so the method can be used in the same file as it
  ;; is defined.
  ;; FIXME: Just like byte-compile-macro-environment, we should have something
  ;; like byte-compile-symbolprop-environment so as to handle these things
  ;; cleanly without affecting the running Emacs.

Anyway, the above expands to

(macroexpand-1 (macroexpand-1 (macroexpand-1 (macroexpand-1 '(defsetf foobar setcar)))))
==>

#+begin_src emacs-lisp
(eval-and-compile
  (put 'foobar 'gv-expander
       (lambda
         (do &rest args)
         (gv--defsetter 'foobar
                        (lambda
                          (val &rest args)
                          `(,'setcar ,@args ,val))
                        do args))))
#+end_src

The `put' is evaluated when the `defsetf' macro call is expanded.
That's what's causing the issue.

AFAIK we don't say that `defsetf' is only allowed at top level, so I
would say (without any judgement) that it's a bug.  And it's not limited
to `defsetf' in "cl".

Michael.