Subject: bug#29220: 26.0.90; eieio-persistent-read fail to restore saved object.

From: Eric Abrahamsen <[email-masked]>
Date: Tue, 05 Dec 2017 14:58:45 -0800

On 12/05/17 17:14 PM, Stefan Monnier wrote:

> Looks good to me.
>
> [ While looking at this code, I notice that with cl-defmethod (which can
>   dispatch not only on EIEIO objects, but other object types as well)
>   we can now fold eieio-override-prin1 into object-write (i.e. make one
>   into an alias for the other).  ]

Yup, I think there's a fair amount of modularization that can be done. I
can make that part of the patch on #29541.

>> If this is okay, it's going into emacs-26, right?
>
> I think so, but we're pretty late in the pretest, so better ask Eli&John
> if they think it's OK for emacs-26.

Okay: John and Eli, this patch is to handle changes in object
implementation in Emacs 26: they are now implemented with records, which
can't be round-tripped with prin1 and read, they have to be written and
read specially. The eieio-persistent mechanism handles that, but
previously did not look inside hash tables or vectors to see if there
were objects in there.

That's causing failure in the pcache library, which other libraries
depend on. I'm hoping we can sneak this in under the wire so that pcache
doesn't fail in Emacs 26.

[...]

On 12/05/17 23:20 PM, Pierre Téchoueyres wrote:
> Eric Abrahamsen <[email-masked]> writes:
>
>> On 12/05/17 14:02 PM, Stefan Monnier wrote:
>>>> Would it be too "heavy" to just copy the object and modify the copy?
>>>
>>> No, that's fine as well.
>>
>> Okay, the attached appears to work just fine. Pierre's recipe passes,
>> as do all the tests in eieio-test-persist. Pierre, maybe you could eval
>> this quickly and make sure that pcache works correctly again?
>
> Yes all my receipes tests are running fine. Many thanks.
> I've tested also with the unicode-fonts package
> (http://github.com/rolandwalker/unicode-fonts) from melpa.
> Everything seem to work fine.

Great! Thanks for testing.

Eric

>From 9f946a968f41e16f7279c72706ccb839dcb7757c Mon Sep 17 00:00:00 2001
From: Eric Abrahamsen <[email-masked]>
Date: Tue, 5 Dec 2017 14:41:50 -0800
Subject: [PATCH] Handle hash tables and vectors when reading/writing EIEIO
 objects

* lisp/emacs-lisp/eieio.el (eieio-override-prin1): EIEIO objects
  printed with `prin1' can no longer be read with `read'. Make sure
  they are printed with object-write instead, even when they're inside
  hash tables and vectors.
* lisp/emacs-lisp/eieio-base.el (eieio-persistent-validate/fix-slot-value):
  Check for written representations of objects inside hash tables and
  vectors, and reconstruct them.
---
 lisp/emacs-lisp/eieio-base.el | 20 ++++++++++++++++++++
 lisp/emacs-lisp/eieio.el      | 19 +++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el
index 58dcd09d7e..0241f27395 100644
--- a/lisp/emacs-lisp/eieio-base.el
+++ b/lisp/emacs-lisp/eieio-base.el
@@ -354,6 +354,26 @@ eieio-persistent-validate/fix-slot-value
 		   proposed-value))
 		 (t
 		  proposed-value))))
+        ;; For hash-tables and vectors, the top-level `read' will not
+        ;; "look inside" member values, so we need to do that
+        ;; explicitly.
+        ((hash-table-p proposed-value)
+         (maphash
+          (lambda (key value)
+            (when (class-p (car-safe value))
+              (setf (gethash key proposed-value)
+                    (eieio-persistent-convert-list-to-object
+                     value))))
+          proposed-value)
+         proposed-value)
+
+        ((vectorp proposed-value)
+         (dotimes (i (length proposed-value))
+           (when (class-p (car-safe (aref proposed-value i)))
+             (aset proposed-value i
+                   (eieio-persistent-convert-list-to-object
+                    (aref proposed-value i)))))
+         proposed-value)
 
 	 ((stringp proposed-value)
 	  ;; Else, check for strings, remove properties.
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index d0d2ff5145..ab96547f93 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -926,6 +926,25 @@ eieio-override-prin1
 	 (object-write thing))
 	((consp thing)
 	 (eieio-list-prin1 thing))
+	((hash-table-p thing)
+         (let ((copy (copy-hash-table thing)))
+	   (maphash
+	    (lambda (key val)
+	      (setf (gethash key copy)
+		    (read
+		     (with-output-to-string
+		       (eieio-override-prin1 val)))))
+	    copy)
+	   (prin1 copy)))
+	((vectorp thing)
+         (let ((copy (copy-sequence thing)))
+	  (dotimes (i (length copy))
+	    (aset copy i
+		  (read
+		   (with-output-to-string
+		     (eieio-override-prin1
+		      (aref copy i))))))
+	  (prin1 copy)))
 	((eieio--class-p thing)
 	 (princ (eieio--class-print-name thing)))
 	(t (prin1 thing))))
-- 
2.15.1