3

Q: are there breaking changes to eieio in Emacs 27?

I just upgraded to the Emacs 27 snapshot, and I'm getting a peculiar break in code that works in previous versions of Emacs.

walkthrough

Here's a toy class and a toy :after method:

(defclass simple-class ()
  ((value
    :initarg :value
    :initform nil
    :documentation "Test slot"))
  "Test class.")

This works:

(simple-class :value "some value") ;; ==> #s(simple-class "some value")

Now I'd like to define an :after method on initialize-instance:

(cl-defmethod initialize-instance :after ((sc simple-class) &key)
  (with-slots (value) sc
    (setf value (upcase value))))

Now it's broken:

(simple-class :value "some value") ;; ==> (error "Keyword argument nil not one of nil")

NB: it's nothing about the content of the :after method: I can define an empty method and I get the same error.

(cl-defmethod initialize-instance :after ((sc simple-class) &key))

what happened?

So: have there been changes to eieio (specifically, cl-defmethod) in Emacs 27 that break previous code? Or is there something bizarre about the snapshot?

Drew
  • 75,699
  • 9
  • 109
  • 225
Dan
  • 32,584
  • 6
  • 98
  • 168
  • Might be incorrect use of `&key` with no following arg name, I think Emacs got stricter about that. By the way, in 25.3, I get `Lisp error: (wrong-type-argument char-or-string-p nil)` after the `cl-defmethod`, did you mean `(simple-class :value "some value")`? – npostavs Jun 09 '19 at 19:58
  • Fixed the typos; sorry. Not sure how else one would define an after method without &keys here. – Dan Jun 09 '19 at 20:09
  • what do you think `&key` means in an expression like `(cl-defun foo (x &key) nil)`? – npostavs Jun 09 '19 at 20:22
  • We need the `&key` to maintain the same number of arguments. Removing `&key` throws an error to that effect. – Dan Jun 09 '19 at 20:31
  • 1
    `C-h n` (`view-emacs-news`) is usually the starting point for *"What's new?"*. – Drew Jun 10 '19 at 02:41

1 Answers1

5

So: have there been changes to eieio (specifically, cl-defmethod) in Emacs 27 that break previous code?

It's not a change in eieio or cl-defmethod directly; what's changed is the handling of the &key symbol in cl-def* macros.

(cl-defmethod initialize-instance :after ((sc simple-class) &key))

In Emacs 26 and earlier this produces a function which accepts any number of arguments (this is a bug: there is only one argument in the arglist, named sc). In Emacs 27 it produces a function which accepts only one argument (sc). The correct argument list for initialize-instance (in all versions of Emacs) would be like this:

(cl-defmethod initialize-instance :after ((sc simple-class) &optional slots))

As told by <f1> f initialize-instance RET:

initialize-instance is a compiled Lisp function in ‘eieio.el’.

(initialize-instance THIS &optional SLOTS)
npostavs
  • 9,033
  • 1
  • 21
  • 53
  • Thank you! NB: the `... &optional slots` version also appears to work with previous versions of Emacs. Where did you find the information about changes to the `cl-def*` macros? I didn't see it in the release news. – Dan Jun 10 '19 at 17:04
  • @Dan I found it by experiment :) It's not in NEWS because it's a bug fix. – npostavs Jun 10 '19 at 20:49