diff options
| author | Noam Postavsky | 2019-05-27 19:05:56 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2019-05-30 18:46:07 -0400 |
| commit | 5f01af6c8e0f7355f7a99a80ff32369071f65eda (patch) | |
| tree | f65280a7140425f0db5ad19782c699a0def2bed5 | |
| parent | 4b24b0185d910d756e85ecdc30f49c414577050e (diff) | |
| download | emacs-5f01af6c8e0f7355f7a99a80ff32369071f65eda.tar.gz emacs-5f01af6c8e0f7355f7a99a80ff32369071f65eda.zip | |
Use plain symbols for eieio type descriptors (Bug#29220)
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.
| -rw-r--r-- | lisp/emacs-lisp/eieio-core.el | 11 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio.el | 3 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el | 28 |
3 files changed, 32 insertions, 10 deletions
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index f879a3999fb..4d55ed6e1d1 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el | |||
| @@ -117,9 +117,6 @@ Currently under control of this var: | |||
| 117 | (defsubst eieio--object-class-tag (obj) | 117 | (defsubst eieio--object-class-tag (obj) |
| 118 | (aref obj 0)) | 118 | (aref obj 0)) |
| 119 | 119 | ||
| 120 | (defsubst eieio--object-class (obj) | ||
| 121 | (eieio--object-class-tag obj)) | ||
| 122 | |||
| 123 | 120 | ||
| 124 | ;;; Important macros used internally in eieio. | 121 | ;;; Important macros used internally in eieio. |
| 125 | 122 | ||
| @@ -132,6 +129,12 @@ Currently under control of this var: | |||
| 132 | (or (cl--find-class class) class) | 129 | (or (cl--find-class class) class) |
| 133 | class)) | 130 | class)) |
| 134 | 131 | ||
| 132 | (defsubst eieio--object-class (obj) | ||
| 133 | (let ((tag (eieio--object-class-tag obj))) | ||
| 134 | (if eieio-backward-compatibility | ||
| 135 | (eieio--class-object tag) | ||
| 136 | tag))) | ||
| 137 | |||
| 135 | (defun class-p (x) | 138 | (defun class-p (x) |
| 136 | "Return non-nil if X is a valid class vector. | 139 | "Return non-nil if X is a valid class vector. |
| 137 | X can also be is a symbol." | 140 | X can also be is a symbol." |
| @@ -163,7 +166,7 @@ Return nil if that option doesn't exist." | |||
| 163 | (defun eieio-object-p (obj) | 166 | (defun eieio-object-p (obj) |
| 164 | "Return non-nil if OBJ is an EIEIO object." | 167 | "Return non-nil if OBJ is an EIEIO object." |
| 165 | (and (recordp obj) | 168 | (and (recordp obj) |
| 166 | (eieio--class-p (eieio--object-class-tag obj)))) | 169 | (eieio--class-p (eieio--object-class obj)))) |
| 167 | 170 | ||
| 168 | (define-obsolete-function-alias 'object-p 'eieio-object-p "25.1") | 171 | (define-obsolete-function-alias 'object-p 'eieio-object-p "25.1") |
| 169 | 172 | ||
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 38436d1f944..864ac2616b9 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el | |||
| @@ -710,6 +710,9 @@ calls `initialize-instance' on that object." | |||
| 710 | ;; Call the initialize method on the new object with the slots | 710 | ;; Call the initialize method on the new object with the slots |
| 711 | ;; that were passed down to us. | 711 | ;; that were passed down to us. |
| 712 | (initialize-instance new-object slots) | 712 | (initialize-instance new-object slots) |
| 713 | (when eieio-backward-compatibility | ||
| 714 | ;; Use symbol as type descriptor, for backwards compatibility. | ||
| 715 | (aset new-object 0 class)) | ||
| 713 | ;; Return the created object. | 716 | ;; Return the created object. |
| 714 | new-object)) | 717 | new-object)) |
| 715 | 718 | ||
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el index dfaa031844f..b87914c75e7 100644 --- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el +++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el | |||
| @@ -277,7 +277,7 @@ persistent class.") | |||
| 277 | :type vector | 277 | :type vector |
| 278 | :initarg :random-vector))) | 278 | :initarg :random-vector))) |
| 279 | 279 | ||
| 280 | (ert-deftest eieio-test-persist-hash-and-vector () | 280 | (defun eieio-test-persist-hash-and-vector () |
| 281 | (let* ((jane (make-instance 'person :name "Jane")) | 281 | (let* ((jane (make-instance 'person :name "Jane")) |
| 282 | (bob (make-instance 'person :name "Bob")) | 282 | (bob (make-instance 'person :name "Bob")) |
| 283 | (hans (make-instance 'person :name "Hans")) | 283 | (hans (make-instance 'person :name "Hans")) |
| @@ -297,10 +297,18 @@ persistent class.") | |||
| 297 | (aset (car (slot-value class 'janitors)) 1 hans) | 297 | (aset (car (slot-value class 'janitors)) 1 hans) |
| 298 | (aset (nth 1 (slot-value class 'janitors)) 1 dierdre) | 298 | (aset (nth 1 (slot-value class 'janitors)) 1 dierdre) |
| 299 | (unwind-protect | 299 | (unwind-protect |
| 300 | ;; FIXME: This should not error. | 300 | (persist-test-save-and-compare class) |
| 301 | (should-error (persist-test-save-and-compare class)) | ||
| 302 | (delete-file (oref class file))))) | 301 | (delete-file (oref class file))))) |
| 303 | 302 | ||
| 303 | (ert-deftest eieio-persist-hash-and-vector-backward-compatibility () | ||
| 304 | (let ((eieio-backward-compatibility t)) ; The default. | ||
| 305 | (eieio-test-persist-hash-and-vector))) | ||
| 306 | |||
| 307 | (ert-deftest eieio-persist-hash-and-vector-no-backward-compatibility () | ||
| 308 | :expected-result :failed ;; Bug#29220. | ||
| 309 | (let ((eieio-backward-compatibility nil)) | ||
| 310 | (eieio-test-persist-hash-and-vector))) | ||
| 311 | |||
| 304 | ;; Extra quotation of lists inside other objects (Gnus registry), also | 312 | ;; Extra quotation of lists inside other objects (Gnus registry), also |
| 305 | ;; bug#29220. | 313 | ;; bug#29220. |
| 306 | 314 | ||
| @@ -315,7 +323,7 @@ persistent class.") | |||
| 315 | :initarg :htab | 323 | :initarg :htab |
| 316 | :type hash-table))) | 324 | :type hash-table))) |
| 317 | 325 | ||
| 318 | (ert-deftest eieio-test-persist-interior-lists () | 326 | (defun eieio-test-persist-interior-lists () |
| 319 | (let* ((thing (make-instance | 327 | (let* ((thing (make-instance |
| 320 | 'eieio-container | 328 | 'eieio-container |
| 321 | :vec [nil] | 329 | :vec [nil] |
| @@ -335,8 +343,16 @@ persistent class.") | |||
| 335 | (setf (nth 2 (cadar alst)) john | 343 | (setf (nth 2 (cadar alst)) john |
| 336 | (nth 2 (cadadr alst)) alexie) | 344 | (nth 2 (cadadr alst)) alexie) |
| 337 | (unwind-protect | 345 | (unwind-protect |
| 338 | ;; FIXME: Should not error. | 346 | (persist-test-save-and-compare thing) |
| 339 | (should-error (persist-test-save-and-compare thing)) | ||
| 340 | (delete-file (slot-value thing 'file))))) | 347 | (delete-file (slot-value thing 'file))))) |
| 341 | 348 | ||
| 349 | (ert-deftest eieio-test-persist-interior-lists-backward-compatibility () | ||
| 350 | (let ((eieio-backward-compatibility t)) ; The default. | ||
| 351 | (eieio-test-persist-interior-lists))) | ||
| 352 | |||
| 353 | (ert-deftest eieio-test-persist-interior-lists-no-backward-compatibility () | ||
| 354 | :expected-result :failed ;; Bug#29220. | ||
| 355 | (let ((eieio-backward-compatibility nil)) | ||
| 356 | (eieio-test-persist-interior-lists))) | ||
| 357 | |||
| 342 | ;;; eieio-test-persist.el ends here | 358 | ;;; eieio-test-persist.el ends here |