]> git.eshelyaron.com Git - emacs.git/commitdiff
Use plain symbols for eieio type descriptors (Bug#29220)
authorNoam Postavsky <npostavs@gmail.com>
Mon, 27 May 2019 23:05:56 +0000 (19:05 -0400)
committerNoam Postavsky <npostavs@gmail.com>
Thu, 30 May 2019 22:46:07 +0000 (18:46 -0400)
Since Emacs 26, eieio objects use a class record (with circular
references) as the type descriptor of the object record.  This causes
problems when reading back an object from a string, because the class
record is not `eq' to the canonical one (which means that read objects
don't satisfy the foo-p predicate).
* lisp/emacs-lisp/eieio.el (make-instance): As a (partial) fix, set
the record's type descriptor to a plain symbol for the type descriptor
when eieio-backward-compatibility is non-nil (the default).
* lisp/emacs-lisp/eieio-core.el (eieio--object-class): Call
eieio--class-object on the type tag when eieio-backward-compatibility
is non-nil.
(eieio-object-p): Use eieio--object-class instead of
eieio--object-class-tag.
* test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
(eieio-test-persist-hash-and-vector)
(eieio-test-persist-interior-lists): Make into functions.
(eieio-persist-hash-and-vector-backward-compatibility)
(eieio-persist-hash-and-vector-no-backward-compatibility)
(eieio-test-persist-interior-lists-backward-compatibility)
(eieio-test-persist-interior-lists-no-backward-compatibility): New
tests which call them, eieio-backward-compatibility let-bound.

lisp/emacs-lisp/eieio-core.el
lisp/emacs-lisp/eieio.el
test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el

index f879a3999fb28766cc42723bb8a7e02a39de4682..4d55ed6e1d1513e203612641fac6b6277266c57a 100644 (file)
@@ -117,9 +117,6 @@ Currently under control of this var:
 (defsubst eieio--object-class-tag (obj)
   (aref obj 0))
 
-(defsubst eieio--object-class (obj)
-  (eieio--object-class-tag obj))
-
 \f
 ;;; Important macros used internally in eieio.
 
@@ -132,6 +129,12 @@ Currently under control of this var:
       (or (cl--find-class class) class)
     class))
 
+(defsubst eieio--object-class (obj)
+  (let ((tag (eieio--object-class-tag obj)))
+    (if eieio-backward-compatibility
+        (eieio--class-object tag)
+      tag)))
+
 (defun class-p (x)
   "Return non-nil if X is a valid class vector.
 X can also be is a symbol."
@@ -163,7 +166,7 @@ Return nil if that option doesn't exist."
 (defun eieio-object-p (obj)
   "Return non-nil if OBJ is an EIEIO object."
   (and (recordp obj)
-       (eieio--class-p (eieio--object-class-tag obj))))
+       (eieio--class-p (eieio--object-class obj))))
 
 (define-obsolete-function-alias 'object-p 'eieio-object-p "25.1")
 
index 38436d1f944c4f89b76b88c4f55950062eb5974d..864ac2616b923647d40b9877e70a3184acb353f7 100644 (file)
@@ -710,6 +710,9 @@ calls `initialize-instance' on that object."
     ;; Call the initialize method on the new object with the slots
     ;; that were passed down to us.
     (initialize-instance new-object slots)
+    (when eieio-backward-compatibility
+      ;; Use symbol as type descriptor, for backwards compatibility.
+      (aset new-object 0 class))
     ;; Return the created object.
     new-object))
 
index dfaa031844fe56db1f19876d2d83bbbb2a6ef5fb..b87914c75e7fb08f48117ca13a9c49b226836aa7 100644 (file)
@@ -277,7 +277,7 @@ persistent class.")
     :type vector
     :initarg :random-vector)))
 
-(ert-deftest eieio-test-persist-hash-and-vector ()
+(defun eieio-test-persist-hash-and-vector ()
   (let* ((jane (make-instance 'person :name "Jane"))
          (bob  (make-instance 'person :name "Bob"))
          (hans (make-instance 'person :name "Hans"))
@@ -297,10 +297,18 @@ persistent class.")
     (aset (car (slot-value class 'janitors)) 1 hans)
     (aset (nth 1 (slot-value class 'janitors)) 1 dierdre)
     (unwind-protect
-        ;; FIXME: This should not error.
-        (should-error (persist-test-save-and-compare class))
+        (persist-test-save-and-compare class)
       (delete-file (oref class file)))))
 
+(ert-deftest eieio-persist-hash-and-vector-backward-compatibility ()
+  (let ((eieio-backward-compatibility t)) ; The default.
+    (eieio-test-persist-hash-and-vector)))
+
+(ert-deftest eieio-persist-hash-and-vector-no-backward-compatibility ()
+  :expected-result :failed ;; Bug#29220.
+  (let ((eieio-backward-compatibility nil))
+    (eieio-test-persist-hash-and-vector)))
+
 ;; Extra quotation of lists inside other objects (Gnus registry), also
 ;; bug#29220.
 
@@ -315,7 +323,7 @@ persistent class.")
     :initarg :htab
     :type hash-table)))
 
-(ert-deftest eieio-test-persist-interior-lists ()
+(defun eieio-test-persist-interior-lists ()
   (let* ((thing (make-instance
                  'eieio-container
                  :vec [nil]
@@ -335,8 +343,16 @@ persistent class.")
     (setf (nth 2 (cadar alst)) john
           (nth 2 (cadadr alst)) alexie)
     (unwind-protect
-        ;; FIXME: Should not error.
-        (should-error (persist-test-save-and-compare thing))
+        (persist-test-save-and-compare thing)
       (delete-file (slot-value thing 'file)))))
 
+(ert-deftest eieio-test-persist-interior-lists-backward-compatibility ()
+  (let ((eieio-backward-compatibility t)) ; The default.
+    (eieio-test-persist-interior-lists)))
+
+(ert-deftest eieio-test-persist-interior-lists-no-backward-compatibility ()
+  :expected-result :failed ;; Bug#29220.
+  (let ((eieio-backward-compatibility nil))
+    (eieio-test-persist-interior-lists)))
+
 ;;; eieio-test-persist.el ends here