Subject: bug#49291: [akater] [PATCH] lisp/emacs-lisp/eieio.el (initialize-instance): Fix initform

From: Stefan Monnier <[email-masked]>
Date: Wed, 30 Jun 2021 09:39:46 -0400

Stefan Monnier [2021-06-30 09:32:32] wrote:

> This is not what happens in eieio.  Rather, initform is evaluated even
> when initarg is present.

Good catch, thanks.

> @@ -756,13 +756,15 @@ defclass eieio-default-superclass nil
>      (dotimes (i (length slots))
>        ;; For each slot, see if we need to evaluate it.
>        (let* ((slot (aref slots i))
> +             (slot-name (eieio-slot-descriptor-name slot))
>               (initform (cl--slot-descriptor-initform slot)))
>          ;; Those slots whose initform is constant already have the right
>          ;; value set in the default-object.
> -        (unless (macroexp-const-p initform)
> +        (unless (or (rassq slot-name
> +                           (eieio--class-initarg-tuples this-class))
> +                    (macroexp-const-p initform))
>            ;; FIXME: We should be able to just do (aset this (+ i <cst>) dflt)!
> -          (eieio-oset this (cl--slot-descriptor-name slot)
> -                      (eval initform t))))))
> +          (eieio-oset this slot-name (eval initform t))))))
>    ;; Shared initialize will parse our slots for us.
>    (shared-initialize this slots))

Hmm... if I read this correctly, you prevents the (eval initform t) for
all slots that were declared with `:initarg <KEYWORD>`, whereas AFAIK the
right semantic is to prevent the (eval initform t) in the case where the
corresponding <KEYWORD> was passed to `make-instance`.

So we should pay attention to `slots` (the arg, not the local var) to
decide whether to skip (eval initform t).

        Stefan