GNU bug report logs -
#78786
31.0.50; eieio-core.el requires byte compilation
Previous Next
Reported by: Pip Cet <pipcet <at> protonmail.com>
Date: Fri, 13 Jun 2025 15:21:01 UTC
Severity: normal
Found in version 31.0.50
Done: Pip Cet <pipcet <at> protonmail.com>
Bug is archived. No further changes may be made.
Full log
View this message in rfc822 format
[Message part 1 (text/plain, inline)]
Your message dated Wed, 09 Jul 2025 15:31:53 +0000
with message-id <87v7o1qt24.fsf <at> protonmail.com>
and subject line Re: bug#78786: 31.0.50; eieio-core.el requires byte compilation
has caused the debbugs.gnu.org bug report #78786,
regarding 31.0.50; eieio-core.el requires byte compilation
to be marked as done.
(If you believe you have received this mail in error, please contact
help-debbugs <at> gnu.org.)
--
78786: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=78786
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
Evaluating eieio-core.el without compilation currently results in
breakage:
(load "eieio-core.el")
(cl-defstruct foo x)
(eieio-oset (make-foo) 'x nil)
results in:
signal(wrong-type-argument (eieio--class #s(cl-structure-class :name foo :docstring nil :parents (#s(cl-structure-class :name cl-structure-object :docstring "The root parent of all \"normal\" CL structs" :parents (#s(built-in-class :name record :docstring "Abstract type of objects with slots." :parents (...) :slots nil :index-table nil)) :slots [] :index-table #<hash-table eq 0/0 ...> :tag cl-structure-object :type nil :named nil :print t :children-sym cl-struct-cl-structure-object-tags)) :slots [#s(cl-slot-descriptor :name x :initform nil :type t :props nil)] :index-table #<hash-table eq 1/1 ...> :tag foo :type nil :named nil :print t :children-sym cl-struct-foo-tags)))
(or (let* ((cl-x cl-x)) (and (memq (type-of cl-x) cl-struct-eieio--class-tags) t)) (signal 'wrong-type-argument (list 'eieio--class cl-x)))
(progn (or (let* ((cl-x cl-x)) (and (memq (type-of cl-x) cl-struct-eieio--class-tags) t)) (signal 'wrong-type-argument (list 'eieio--class cl-x))) (aref cl-x 4))
(let* ((cl-x class)) (progn (or (let* ((cl-x cl-x)) (and (memq (type-of cl-x) cl-struct-eieio--class-tags) t)) (signal 'wrong-type-argument (list 'eieio--class cl-x))) (aref cl-x 4)))
(aref (let* ((cl-x class)) (progn (or (let* ((cl-x cl-x)) (and (memq (type-of cl-x) cl-struct-eieio--class-tags) t)) (signal 'wrong-type-argument (list 'eieio--class cl-x))) (aref cl-x 4))) slot-idx)
(let* ((sd (aref (let* ((cl-x class)) (progn (or (let* ... ...) (signal ... ...)) (aref cl-x 4))) slot-idx)) (st (let* ((cl-x sd)) (progn (or (let* (...) (and ... t)) (signal 'wrong-type-argument (list ... cl-x))) (aref cl-x 3))))) (cond ((not (eieio--perform-slot-validation st value)) (signal 'invalid-slot-type (list (let* ((cl-x class)) (progn (or ... ...) (aref cl-x 1))) slot st value))) ((alist-get :read-only (let* ((cl-x sd)) (progn (or (let* ... ...) (signal ... ...)) (aref cl-x 4)))) (signal 'eieio-read-only (list (let* ((cl-x class)) (progn (or ... ...) (aref cl-x 1))) slot)))))
(if eieio-skip-typecheck nil (setq slot-idx (- slot-idx '1)) (let* ((sd (aref (let* ((cl-x class)) (progn (or ... ...) (aref cl-x 4))) slot-idx)) (st (let* ((cl-x sd)) (progn (or (let* ... ...) (signal ... ...)) (aref cl-x 3))))) (cond ((not (eieio--perform-slot-validation st value)) (signal 'invalid-slot-type (list (let* (...) (progn ... ...)) slot st value))) ((alist-get :read-only (let* ((cl-x sd)) (progn (or ... ...) (aref cl-x 4)))) (signal 'eieio-read-only (list (let* (...) (progn ... ...)) slot))))))
eieio--validate-slot-value(#s(cl-structure-class :name foo :docstring nil :parents (#s(cl-structure-class :name cl-structure-object :docstring "The root parent of all \"normal\" CL structs" :parents (#s(built-in-class :name record :docstring "Abstract type of objects with slots." :parents (#s(built-in-class :name atom :docstring "Abstract supertype of anything but cons cells." :parents ... :slots nil :index-table nil)) :slots nil :index-table nil)) :slots [] :index-table #<hash-table eq 0/0 ...> :tag cl-structure-object :type nil :named nil :print t :children-sym cl-struct-cl-structure-object-tags)) :slots [#s(cl-slot-descriptor :name x :initform nil :type t :props nil)] :index-table #<hash-table eq 1/1 ...> :tag foo :type nil :named nil :print t :children-sym cl-struct-foo-tags) 1 nil x)
The expected behavior is for this code to complete without error.
The failure is because eieio--validate-slot-value is called for a class
(object) of type cl-structure-object, but calls eieio--class-slots on
that object; it could call cl--class-slots instead, and then this bug
wouldn't happen.
When byte-compiled, we optimize out the type checks so everything works.
This is achieved by the cl-declaim calls surrounding the cl-defstruct of
eieio--class.
When interpreted directly, cl-defstruct always adds the type checks, so
the error pops up.
However, I have my doubts about whether we might end up calling
eieio--class-class-slots or eieio--class-initarg-tuples on a
cl-structure-object, which would return its "type" or "named" slots
(unless I miscounted, sorry). So I'd like to fix these while we're
there (in the latter case, we're on slow code paths so this should not
be a problem; in the former case, if there is a performance impact, we
could consider moving the class-slots slot to cl--class instead,
reserving a useless slot in it for cl-structure-object objects).
I propose moving to cl--class-* accessors where we can, and calling
eieio--class-slot-name-index and eieio--class-initarg-to-attribute only
on known/checked eieio--class objects.
But if an alternative is desired (I think this may be the case because I
suggested changing one of the accessors before), and the
initarg/class-slot case is always safe, we could simply error out when
trying to evaluate eieio-core.el directly rather than compiling it.
While this is related to bug#78685, I think there are other,
non-bug-induced circumstances in which we end up interpreting
eieio-core.el, so we should either allow it or make it fail less subtly.
[Message part 3 (message/rfc822, inline)]
"Stefan Monnier" <monnier <at> iro.umontreal.ca> writes:
>>> Yes, calling `eieio--class-slot-name-index` on non-EIEIO classes is
>>> a bug, we should fix the code to do it only when it is an EIEIO class.
>>
>> So this?
>
> LGTM, yes.
Pushed, thanks. Closing this bug optimistically.
>> @@ -808,8 +810,9 @@ eieio-oset
>> (if (not c)
>> ;; It might be missing because it is a :class allocated slot.
>> ;; Let's check that info out.
>> - (if (setq c
>> - (eieio--class-slot-name-index class slot))
>> + (if (and (eieie--class-p class)
^
Fixed this one.
Pip
This bug report was last modified 8 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.