GNU bug report logs - #38000
27.0.50; [PATCH] WIP on using gnus info accessor macros

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: emacs; Reported by: Eric Abrahamsen <eric@HIDDEN>; Keywords: patch; dated Thu, 31 Oct 2019 00:00:02 UTC; Maintainer for emacs is bug-gnu-emacs@HIDDEN.

Message received at 38000 <at> debbugs.gnu.org:


Received: (at 38000) by debbugs.gnu.org; 2 Nov 2019 14:43:51 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Nov 02 10:43:51 2019
Received: from localhost ([127.0.0.1]:32813 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQud5-0005vo-4T
	for submit <at> debbugs.gnu.org; Sat, 02 Nov 2019 10:43:51 -0400
Received: from quimby.gnus.org ([80.91.231.51]:56110)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <larsi@HIDDEN>) id 1iQud3-0005vf-P5
 for 38000 <at> debbugs.gnu.org; Sat, 02 Nov 2019 10:43:50 -0400
Received: from cm-84.212.202.86.getinternet.no ([84.212.202.86] helo=marnie)
 by quimby.gnus.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.89) (envelope-from <larsi@HIDDEN>)
 id 1iQucz-0003Y7-IT; Sat, 02 Nov 2019 15:43:47 +0100
From: Lars Ingebrigtsen <larsi@HIDDEN>
To: Eric Abrahamsen <eric@HIDDEN>
Subject: Re: bug#38000: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN> <87ftj9m7q4.fsf@HIDDEN>
 <8736f8bu7r.fsf@HIDDEN> <87v9s33e3s.fsf@HIDDEN>
 <877e4jlbco.fsf@HIDDEN>
 <87sgn7jjk3.fsf@HIDDEN>
Date: Sat, 02 Nov 2019 15:43:45 +0100
In-Reply-To: <87sgn7jjk3.fsf@HIDDEN> (Eric Abrahamsen's message of
 "Fri, 01 Nov 2019 15:52:44 -0700")
Message-ID: <87imo2fie6.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org",
 has NOT identified this incoming email as spam.  The original
 message has been attached to this so you can view it or label
 similar future email.  If you have any questions, see
 @@CONTACT_ADDRESS@@ for details.
 Content preview:  Eric Abrahamsen <eric@HIDDEN> writes: > Okay,
 here's what the patch looks like now. [...] 
 Content analysis details:   (-2.9 points, 5.0 required)
 pts rule name              description
 ---- ---------------------- --------------------------------------------------
 -1.0 ALL_TRUSTED            Passed through trusted hosts only via SMTP
 -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
 [score: 0.0000]
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 38000
Cc: 38000 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Eric Abrahamsen <eric@HIDDEN> writes:

> Okay, here's what the patch looks like now.

[...]

> I think that's it... This still needs some testing, but I'm optimistic.

It all sounds good to me.  I've just skimmed the patch (which is very
big, but mostly with "mechanical" substitutions), and it looks fine to
me.  But, yes, thorough testing would be nice.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at 38000 <at> debbugs.gnu.org:


Received: (at 38000) by debbugs.gnu.org; 1 Nov 2019 22:52:58 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Nov 01 18:52:58 2019
Received: from localhost ([127.0.0.1]:57452 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQfmq-0005Ni-U0
	for submit <at> debbugs.gnu.org; Fri, 01 Nov 2019 18:52:58 -0400
Received: from ericabrahamsen.net ([52.70.2.18]:48966
 helo=mail.ericabrahamsen.net)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <eric@HIDDEN>) id 1iQfmn-0005NS-8a
 for 38000 <at> debbugs.gnu.org; Fri, 01 Nov 2019 18:52:55 -0400
Received: from localhost (c-73-254-86-141.hsd1.wa.comcast.net [73.254.86.141])
 (Authenticated sender: eric@HIDDEN)
 by mail.ericabrahamsen.net (Postfix) with ESMTPSA id C7B3CFA089;
 Fri,  1 Nov 2019 22:52:45 +0000 (UTC)
From: Eric Abrahamsen <eric@HIDDEN>
To: Lars Ingebrigtsen <larsi@HIDDEN>
Subject: Re: bug#38000: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN> <87ftj9m7q4.fsf@HIDDEN>
 <8736f8bu7r.fsf@HIDDEN> <87v9s33e3s.fsf@HIDDEN>
 <877e4jlbco.fsf@HIDDEN>
Date: Fri, 01 Nov 2019 15:52:44 -0700
In-Reply-To: <877e4jlbco.fsf@HIDDEN> (Eric Abrahamsen's message of
 "Fri, 01 Nov 2019 11:07:03 -0700")
Message-ID: <87sgn7jjk3.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: 38000
Cc: 38000 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

--=-=-=
Content-Type: text/plain

Eric Abrahamsen <eric@HIDDEN> writes:

> Lars Ingebrigtsen <larsi@HIDDEN> writes:
>
>> Eric Abrahamsen <eric@HIDDEN> writes:
>>
>>> Huh, I didn't realize that list-based structs didn't put a tag in the
>>> `car' position unless you pass the :named keyword.
>>>
>>> We could switch to list-based structs without breaking out-of-tree code,
>>> but I don't see much point: you can't use them for generic function
>>> dispatch, even when they're :named, nor do you get a NAME-p predicate
>>> for free. That doesn't leave much point.
>>
>> It means that you don't have to write the accessor macros by hand.  :-)
>
> But you already did! :)
>
> Okay, let's use them anyway. And I'd like to move the "extend" and
> "vacuum" procedures to the reading and writing of the newsrc.eld file,
> so the rest of the code can forget about it. I'll leave the setter
> macros in place, and continue to accept (and ignore) an EXTEND argument,
> so other people's code continues to work.

Okay, here's what the patch looks like now.

1. gnus-info is defined with defstruct, and the constructor arglist
looks like: (group rank read &optional marks method params), meaning
that if you have an info list that may or may not be fully extended, you
can run it through the constructor and all the missing elements will be
set to their default (nil).

2. This is done when reading the newsrc.eld file (and creating new
groups), and all the other uses of the 'extend argument have been
removed.`

3. The bit that chops off nils from the end of infos has been moved from
`gnus-update-marks' to `gnus-gnus-to-quick-newsrc-format', so it only
happens right at the last minute, when saving.

4. I've changed `gnus-set-info' to update each element of an info
individually, rather than just replacing the whole thing. This looks
stupid, but preserves object reference, meaning we no longer need to mess
with the `gnus-newsrc-alist' in `gnus-group-set-info', which was causing
trouble for people. It's going to be a bit slower, but I don't think this is
super performance-crucial.

I think that's it... This still needs some testing, but I'm optimistic.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-WIP-on-using-gnus-info-accessors.patch

From 56f4dacf5c1062b156df46778644e65378a9b4a2 Mon Sep 17 00:00:00 2001
From: Eric Abrahamsen <eric@HIDDEN>
Date: Wed, 17 Jul 2019 18:49:27 -0700
Subject: [PATCH] WIP on using gnus info accessors

---
 lisp/gnus/gnus-agent.el |  36 ++++++------
 lisp/gnus/gnus-group.el |  80 +++++++++++++-------------
 lisp/gnus/gnus-int.el   |   2 +-
 lisp/gnus/gnus-sieve.el |   2 +-
 lisp/gnus/gnus-start.el |  79 ++++++++++++++------------
 lisp/gnus/gnus-sum.el   |  49 +++++++---------
 lisp/gnus/gnus.el       | 122 ++++++++++++++++++++++++----------------
 lisp/gnus/nndiary.el    |   5 +-
 lisp/gnus/nndraft.el    |  18 +++---
 lisp/gnus/nnimap.el     |  23 ++++----
 lisp/gnus/nnir.el       |   8 +--
 lisp/gnus/nnmaildir.el  |  10 ++--
 lisp/gnus/nnmairix.el   |  38 ++++++-------
 lisp/gnus/nnml.el       |   4 +-
 lisp/gnus/nnvirtual.el  |  17 +++---
 15 files changed, 252 insertions(+), 241 deletions(-)

diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 1f25255278..a58a35df98 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -1212,22 +1212,21 @@ gnus-agent-synchronize-group-flags
 	      (marks (nth 2 action)))
 	  (dolist (mark marks)
 	    (cond ((eq mark 'read)
-		   (gnus-info-set-read
-		    info
-		    (funcall (if (eq what 'add)
-				 'gnus-range-add
-			       'gnus-remove-from-range)
-			     (gnus-info-read info)
-			     range))
+		   (setf (gnus-info-read info)
+			 (funcall (if (eq what 'add)
+				      'gnus-range-add
+				    'gnus-remove-from-range)
+				  (gnus-info-read info)
+				  range))
 		   (gnus-get-unread-articles-in-group
 		    info
 		    (gnus-active (gnus-info-group info))))
 		  ((memq mark '(tick))
 		   (let ((info-marks (assoc mark (gnus-info-marks info))))
 		     (unless info-marks
-                       (gnus-info-set-marks
-                        info (cons (setq info-marks (list mark))
-                                   (gnus-info-marks info))))
+		       (setf (gnus-info-marks info)
+			     (cons (setq info-marks (list mark))
+				   (gnus-info-marks info))))
                      (setcdr info-marks
                              (funcall (if (eq what 'add)
                                           'gnus-range-add
@@ -1303,12 +1302,11 @@ gnus-agent-possibly-alter-active
           ;; file.
 
           (let ((read (gnus-info-read info)))
-            (gnus-info-set-read
-             info
-             (gnus-range-add
-              read
-              (list (cons (1+ agent-max)
-                          (1- active-min))))))
+	    (setf (gnus-info-read info)
+		  (gnus-range-add
+		   read
+		   (list (cons (1+ agent-max)
+                               (1- active-min))))))
 
           ;; Lie about the agent's local range for this group to
           ;; disable the set read each time this server is opened.
@@ -2535,11 +2533,11 @@ gnus-agent-fetch-group-1
                           (when (cdr marked-arts)
                             (setq marks
 				  (delq marked-arts (gnus-info-marks info)))
-                            (gnus-info-set-marks info marks)))))
+			    (setf (gnus-info-marks info) marks)))))
                     (let ((read (gnus-info-read
 				 (or info (setq info (gnus-get-info group))))))
-                      (gnus-info-set-read
-		       info (gnus-add-to-range read unfetched-articles)))
+		      (setf (gnus-info-read info)
+			    (gnus-add-to-range read unfetched-articles)))
 
                     (gnus-group-update-group group t)
                     (sit-for 0)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 8f5f5d66e4..0d3649120d 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1423,7 +1423,7 @@ gnus-group-update-group-line
 	   (not (gnus-ephemeral-group-p group))
 	   (gnus-dribble-enter
 	    (concat "(gnus-group-set-info '"
-		    (gnus-prin1-to-string (nth 1 entry))
+		    (gnus-prin1-to-string (gnus-get-info group))
 		    ")")
 	    (concat "^(gnus-group-set-info '(\"" (regexp-quote group) "\"")))
       (setq gnus-group-indentation (gnus-group-group-indentation))
@@ -1440,10 +1440,10 @@ gnus-group-insert-group-line-info
     (if entry
 	(progn
 	  ;; (Un)subscribed group.
-	  (setq info (nth 1 entry))
+	  (setq info (gnus-get-info group))
 	  (gnus-group-insert-group-line
 	   group (gnus-info-level info) (gnus-info-marks info)
-	   (or (car entry) t) (gnus-info-method info)))
+	   (or (gnus-group-unread group) t) (gnus-info-method info)))
       ;; This group is dead.
       (gnus-group-insert-group-line
        group
@@ -1457,7 +1457,7 @@ gnus-group-insert-group-line-info
        (gnus-method-simplify (gnus-find-method-for-group group))))))
 
 (defun gnus-number-of-unseen-articles-in-group (group)
-  (let* ((info (nth 1 (gnus-group-entry group)))
+  (let* ((info (gnus-get-info group))
 	 (marked (gnus-info-marks info))
 	 (seen (cdr (assq 'seen marked)))
 	 (active (gnus-active group)))
@@ -1595,15 +1595,15 @@ gnus-group-update-eval-form
   "Eval `car' of each element of LIST, and return the first that return t.
 Some value are bound so the form can use them."
   (when list
-    (let* ((entry (gnus-group-entry group))
+    (let* ((unread (gnus-group-unread group))
            (active (gnus-active group))
-           (info (nth 1 entry))
+           (info (gnus-get-info group))
            (method (inline (gnus-server-get-method
 			    group (gnus-info-method info))))
            (marked (gnus-info-marks info))
 	   (env
 	    (list
-	     (cons 'unread (if (numberp (car entry)) (car entry) 0))
+	     (cons 'unread (if (numberp unread) unread 0))
 	     (cons 'total (if active (1+ (- (cdr active) (car active))) 0))
 	     (cons 'mailp (apply
 			   'append
@@ -1676,7 +1676,7 @@ gnus-group-update-group
 			 (not (gnus-ephemeral-group-p group)))
 		(gnus-dribble-enter
 		 (concat "(gnus-group-set-info '"
-			 (gnus-prin1-to-string (nth 1 entry))
+			 (gnus-prin1-to-string (gnus-get-info group))
 			 ")")
 		 (concat "^(gnus-group-set-info '(\""
 			 (regexp-quote group) "\"")))))
@@ -2752,7 +2752,9 @@ gnus-group-make-group
       (error "Group %s already exists" nname))
     ;; Subscribe to the new group.
     (gnus-group-change-level
-     (setq info (list t nname gnus-level-default-subscribed nil nil meth))
+     (setq info (list t (make-gnus-info
+			 nname
+			 gnus-level-default-subscribed nil nil meth)))
      gnus-level-default-subscribed gnus-level-killed
      (gnus-group-group-name) t)
     ;; Make it active.
@@ -2958,9 +2960,9 @@ gnus-group-edit-group-done
 			(if (or (not method)
 				(gnus-server-equal
 				 gnus-select-method method))
-			    (gnus-group-real-name (car info))
+			    (gnus-group-real-name group)
 			  (gnus-group-prefixed-name
-			   (gnus-group-real-name (car info)) method))
+			   (gnus-group-real-name group) method))
 		      nil)))
     (when (and new-group
 	       (not (equal new-group group)))
@@ -2973,11 +2975,11 @@ gnus-group-edit-group-done
       (setq info (copy-tree info))
       (setcar info new-group)
       (unless (gnus-server-equal method "native")
-	(unless (nthcdr 3 info)
+	(unless (gnus-info-marks info)
 	  (nconc info (list nil nil)))
-	(unless (nthcdr 4 info)
+	(unless (gnus-info-method info)
 	  (nconc info (list nil)))
-	(gnus-info-set-method info method))
+	(setf (gnus-info-method info) method))
       (gnus-group-set-info info))
     (gnus-group-update-group (or new-group group))
     (gnus-group-position-point)))
@@ -3531,17 +3533,17 @@ gnus-info-clear-data
     (gnus-undo-register
       `(progn
 	 (gnus-request-set-mark ,group ',action)
-	 (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-	 (gnus-info-set-read ',info ',(gnus-info-read info))
+	 (setf (gnus-info-marks ',info) ',(gnus-info-marks info) t)
+	 (setf (gnus-info-read ',info) ',(gnus-info-read info))
 	 (when (gnus-group-jump-to-group ,group)
 	   (gnus-get-unread-articles-in-group ',info ',(gnus-active group) t)
 	   (gnus-group-update-group-line))))
     (setq action (mapcar (lambda (el) (list (nth 0 el) 'del (nth 2 el)))
 			 action))
     (gnus-request-set-mark group action)
-    (gnus-info-set-read info nil)
+    (setf (gnus-info-read info) nil)
     (when (gnus-info-marks info)
-      (gnus-info-set-marks info nil))))
+      (setf (gnus-info-marks info) nil))))
 
 ;; Group catching up.
 
@@ -3903,7 +3905,7 @@ gnus-group-yank-group
     (while (>= (cl-decf arg) 0)
       (when (not (setq info (pop gnus-list-of-killed-groups)))
 	(error "No more newsgroups to yank"))
-      (push (setq group (nth 1 info)) out)
+      (push (setq group (gnus-info-group info)) out)
       ;; Find which newsgroup to insert this one before - search
       ;; backward until something suitable is found.  If there are no
       ;; other newsgroups in this buffer, just make this newsgroup the
@@ -4413,6 +4415,7 @@ gnus-group-browse-foreign-server
   (gnus-browse-foreign-server method))
 
 (defun gnus-group-set-info (info &optional method-only-group part)
+  "Update status for group represented by INFO."
   (when (or info part)
     (let* ((entry (gnus-group-entry
 		   (or method-only-group (gnus-info-group info))))
@@ -4459,20 +4462,12 @@ gnus-group-set-info
       ;; can do the update.
       (if entry
 	  (progn
-	    (setcar (nthcdr 1 entry) info)
+	    (gnus-set-info (nthcdr 1 entry) info)
 	    (when (and (not (eq (car entry) t))
 		       (gnus-active (gnus-info-group info)))
-	      (setcar entry (length
-			     (gnus-list-of-unread-articles (car info)))))
-	    ;; The above `setcar' will only affect the hashtable, not
-	    ;; the alist: update the alist separately, but only if
-	    ;; it's been initialized.
-	    (when gnus-newsrc-alist
-	      (push info (cdr (setq gnus-newsrc-alist
-				    (remove (assoc-string
-					     (gnus-info-group info)
-					     gnus-newsrc-alist)
-					    gnus-newsrc-alist))))))
+	      (setf (gnus-group-unread (gnus-info-group info))
+		    (length
+		     (gnus-list-of-unread-articles (car info))))))
 	(error "No such group: %s" (gnus-info-group info))))))
 
 ;; Ad-hoc function for inserting data from a different newsrc.eld
@@ -4497,20 +4492,23 @@ gnus-add-marked-articles
   (let ((info (or info (gnus-get-info group)))
 	marked m)
     (or (not info)
-	(and (not (setq marked (nthcdr 3 info)))
+	(and (not (setq marked (gnus-info-marks info)))
 	     (or (null articles)
-		 (setcdr (nthcdr 2 info)
-			 (list (list (cons type (gnus-compress-sequence
-						 articles t)))))))
-	(and (not (setq m (assq type (car marked))))
+		 ;; Group had no marks at all, set unconditionally.
+		 (setf (gnus-info-marks info)
+		       (list (cons type (gnus-compress-sequence
+					 articles t))))))
+	(and (not (setq m (assq type marked)))
 	     (or (null articles)
-		 (setcar marked
-			 (cons (cons type (gnus-compress-sequence articles t) )
-			       (car marked)))))
+		 ;; Group had no marks of TYPE.
+		 (setf (gnus-info-marks info)
+		       (cons (cons type (gnus-compress-sequence articles t))
+			     marked))))
 	(if force
+	    ;; Replace (or remove) all marks of TYPE.
 	    (if (null articles)
-		(setcar (nthcdr 3 info)
-			(assq-delete-all type (car marked)))
+		(setf (gnus-info-marks info)
+		      (assq-delete-all type marked))
 	      (setcdr m (gnus-compress-sequence articles t)))
 	  (setcdr m (gnus-compress-sequence
 		     (sort (nconc (gnus-uncompress-range (cdr m))
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 0abbfe6720..a21bc25840 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -727,7 +727,7 @@ gnus-request-marks
 	       (let* ((range (if (= min 2) 1 (cons 1 (1- min))))
 		      (read (gnus-info-read info))
 		      (new-read (gnus-range-add read (list range))))
-		 (gnus-info-set-read info new-read)))
+		 (setf (gnus-info-read info) new-read)))
 	     info)))))
 
 (defun gnus-request-expire-articles (articles group &optional force)
diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el
index fc0bf3098b..5edd6f5f7a 100644
--- a/lisp/gnus/gnus-sieve.el
+++ b/lisp/gnus/gnus-sieve.el
@@ -128,7 +128,7 @@ gnus-sieve-article-add-rule
 	  (info (gnus-get-info gnus-newsgroup-name)))
       (if (null rule)
 	  (error "Could not guess rule for article")
-	(gnus-info-set-params info (cons rule (gnus-info-params info)))
+	(push rule (gnus-info-params info))
 	(message "Added rule in group %s for article: %s" gnus-newsgroup-name
 		 rule)))))
 
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index e142c438ee..70e63188c9 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1295,7 +1295,7 @@ gnus-group-change-level
        (t
 	(when (and (>= level gnus-level-zombie)
 		   entry)
-	  (remhash (car (nth 1 entry)) gnus-newsrc-hashtb)
+	  (remhash group gnus-newsrc-hashtb)
 	  (setq gnus-group-list (remove group gnus-group-list))
 	  (setq gnus-newsrc-alist (delq (assoc group gnus-newsrc-alist)
 					gnus-newsrc-alist)))))
@@ -1323,7 +1323,7 @@ gnus-group-change-level
 	    ;; It was alive, and it is going to stay alive, so we
 	    ;; just change the level and don't change any pointers or
 	    ;; hash table entries.
-	    (setcar (cdadr entry) level)
+	    (setf (gnus-info-level (nth 1 entry)) level)
 	  (if (listp entry)
 	      (setq info (cdr entry)
 		    num (car entry))
@@ -1577,7 +1577,7 @@ gnus-get-unread-articles-in-group
       ;; Set the number of unread articles.
       (when (and info
 		 (gnus-group-entry (gnus-info-group info)))
-	(setcar (gnus-group-entry (gnus-info-group info)) num))
+	(setf (gnus-group-unread (gnus-info-group info)) num))
       num)))
 
 ;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
@@ -1603,7 +1603,7 @@ gnus-get-unread-articles
 	 (gnus-agent-article-local-times 0)
 	 (archive-method (gnus-server-to-method "archive"))
 	 infos info group active method cmethod
-	 method-type method-group-list entry)
+	 method-type method-group-list)
     (gnus-message 6 "Checking new news...")
 
     (while newsrc
@@ -1650,8 +1650,8 @@ gnus-get-unread-articles
 	;; It leads `(gnus-group-unread group)' to return t.  See also
 	;; `gnus-group-prepare-flat'.
 	(unless active
-	  (when (setq entry (gnus-group-entry group))
-	    (setcar entry t)))))
+	  (when (gnus-group-entry group)
+	    (setf (gnus-group-unread group) t)))))
 
     ;; Sort the methods based so that the primary and secondary
     ;; methods come first.  This is done for legacy reasons to try to
@@ -1824,17 +1824,17 @@ gnus-make-hashtable-from-newsrc-alist
 		    gnus-newsrc-alist
 		  (cons (list "dummy.group" 0 nil) alist))))
     (while alist
-      (setq info (car alist))
+      (setq info (apply #'make-gnus-info (car alist)))
       ;; Make the same select-methods identical Lisp objects.
       (when (setq method (gnus-info-method info))
 	(if (setq rest (member method methods))
-	    (gnus-info-set-method info (car rest))
+	    (setf (gnus-info-method info) (car rest))
 	  (push method methods)))
       ;; Check for encoded group names and decode them.
-      (when (string-match-p "[^[:ascii:]]" (setq gname (car info)))
+      (when (string-match-p "[^[:ascii:]]" (setq gname (gnus-info-group info)))
 	(let ((decoded (gnus-group-decoded-name gname)))
 	 (setf gname decoded
-	       (car info) decoded)))
+	       (gnus-info-group info) decoded)))
       ;; Check for duplicates.
       (if (gethash gname gnus-newsrc-hashtb)
 	  ;; Remove this entry from the alist.
@@ -1879,9 +1879,9 @@ gnus-parse-active
 
 (defun gnus-make-articles-unread (group articles)
   "Mark ARTICLES in GROUP as unread."
-  (let* ((info (nth 1 (or (gnus-group-entry group)
-			  (gnus-group-entry
-			   (gnus-group-real-name group)))))
+  (let* ((info (or (gnus-get-info group)
+		   (gnus-get-info
+		    (gnus-group-real-name group))))
 	 (ranges (gnus-info-read info))
 	 news article)
     (while articles
@@ -1890,8 +1890,8 @@ gnus-make-articles-unread
 	(push article news)))
     (when news
       ;; Enter this list into the group info.
-      (gnus-info-set-read
-       info (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
+      (setf (gnus-info-read info)
+	    (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
 
       ;; Set the number of unread articles in gnus-newsrc-hashtb.
       (gnus-get-unread-articles-in-group info (gnus-active group))
@@ -1901,9 +1901,8 @@ gnus-make-articles-unread
 
 (defun gnus-make-ascending-articles-unread (group articles)
   "Mark ascending ARTICLES in GROUP as unread."
-  (let* ((entry (or (gnus-group-entry group)
-                    (gnus-group-entry (gnus-group-real-name group))))
-         (info (nth 1 entry))
+  (let* ((info (or (gnus-get-info group)
+                   (gnus-get-info (gnus-group-real-name group))))
 	 (ranges (gnus-info-read info))
          (r ranges)
 	 modified)
@@ -1911,7 +1910,7 @@ gnus-make-ascending-articles-unread
     (while articles
       (let ((article (pop articles))) ; get the next article to remove from ranges
         (while (let ((range (car ranges))) ; note the current range
-                 (if (atom range)       ; single value range
+                 (if (atom range)	   ; single value range
                      (cond ((not range)
                             ;; the articles extend past the end of the ranges
                             ;; OK - I'm done
@@ -1958,7 +1957,7 @@ gnus-make-ascending-articles-unread
       (when (eq modified 'remove-null)
         (setq r (delq nil r)))
       ;; Enter this list into the group info.
-      (gnus-info-set-read info r)
+      (setf (gnus-info-read info) r)
 
       ;; Set the number of unread articles in gnus-newsrc-hashtb.
       (gnus-get-unread-articles-in-group info (gnus-active group))
@@ -2362,12 +2361,11 @@ gnus-convert-old-ticks
 	(setq dormant (cdr (assq 'dormant marks))
 	      ticked (cdr (assq 'tick marks)))
 	(when (or dormant ticked)
-	  (gnus-info-set-read
-	   info
-	   (gnus-add-to-range
-	    (gnus-info-read info)
-	    (nconc (gnus-uncompress-range dormant)
-		   (gnus-uncompress-range ticked)))))))))
+	  (setf (gnus-info-read info)
+		(gnus-add-to-range
+		 (gnus-info-read info)
+		 (nconc (gnus-uncompress-range dormant)
+			(gnus-uncompress-range ticked)))))))))
 
 (defun gnus-load (file)
   "Load FILE, but in such a way that read errors can be reported."
@@ -2438,9 +2436,9 @@ gnus-read-old-newsrc-el-file
       (while (setq group (pop newsrc))
 	(if (setq info (gnus-get-info (car group)))
 	    (progn
-	      (gnus-info-set-read info (cddr group))
-	      (gnus-info-set-level
-	       info (if (nth 1 group) gnus-level-default-subscribed
+	      (setf (gnus-info-read info) (cddr group))
+	      (setf (gnus-info-level info)
+		    (if (nth 1 group) gnus-level-default-subscribed
 		      gnus-level-default-unsubscribed))
 	      (push info gnus-newsrc-alist))
 	  (push (setq info
@@ -2451,10 +2449,10 @@ gnus-read-old-newsrc-el-file
 		gnus-newsrc-alist))
 	;; Copy marks into info.
 	(when (setq m (assoc (car group) marked))
-	  (unless (nthcdr 3 info)
+	  (unless (gnus-info-marks info)
 	    (nconc info (list nil)))
-	  (gnus-info-set-marks
-	   info (list (cons 'tick (gnus-compress-sequence
+	  (setf (gnus-info-marks info)
+		(list (cons 'tick (gnus-compress-sequence
 				   (sort (cdr m) '<) t))))))
       (setq newsrc killed)
       (while newsrc
@@ -2609,7 +2607,7 @@ gnus-newsrc-to-gnus-format
 		;; There is an entry for this file in
 		;; `gnus-newsrc-hashtb'.
 		(progn
-		  (gnus-info-set-read info (nreverse reads))
+		  (setf (gnus-info-read info) (nreverse reads))
 		  ;; We update the level very gently.  In fact, we
 		  ;; only change it if there's been a status change
 		  ;; from subscribed to unsubscribed, or vice versa.
@@ -2621,7 +2619,7 @@ gnus-newsrc-to-gnus-format
 				       (1+ gnus-level-default-unsubscribed))))
 			((and (> level gnus-level-subscribed) subscribed)
 			 (setq level gnus-level-default-subscribed)))
-		  (gnus-info-set-level info level))
+		  (setf (gnus-info-level info) level))
 	      ;; This is a new group.
 	      (setq info (list group
 			       (if subscribed
@@ -2645,7 +2643,7 @@ gnus-newsrc-to-gnus-format
 	    (prev gnus-newsrc-alist)
 	    entry mentry)
 	(while rc
-	  (or (null (nth 4 (car rc)))	; It's a native group.
+	  (or (null (gnus-info-method (car rc))) ; It's a native group.
 	      (assoc (caar rc) newsrc)	; It's already in the alist.
 	      (if (setq entry (assoc (caar prev) newsrc))
 		  (setcdr (setq mentry (memq entry newsrc))
@@ -2903,7 +2901,14 @@ gnus-gnus-to-quick-newsrc-format
 	   ;; `gnus-read-newsrc-el-file' into a conversion routine.
 	   (gnus-newsrc-alist
 	    (mapcar (lambda (info)
-		      (cons (encode-coding-string (car info) 'utf-8-emacs)
+		      (let ((i 5))
+			;; Don't write unnecessary nils to disk.
+			(while (and (> i 2)
+				    (not (nth i info)))
+			  (when (nthcdr (cl-decf i) info)
+			    (setcdr (nthcdr i info) nil))))
+		      (cons (encode-coding-string
+			     (gnus-info-group info) 'utf-8-emacs)
 			    (cdr info)))
 		    gnus-newsrc-alist))
 	   (gnus-topic-alist
@@ -2952,7 +2957,7 @@ gnus-gnus-to-newsrc-format
 	(insert gnus-newsrc-options))
       ;; Write subscribed and unsubscribed.
       (dolist (g-name groups)
-	(setq info (nth 1 (gnus-group-entry g-name)))
+	(setq info (gnus-get-info g-name))
 	;; Maybe don't write foreign groups to .newsrc.
 	(when (or (null (setq method (gnus-info-method info)))
 		  (equal method "native")
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index f21bc7584e..75bc9acb66 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -6172,18 +6172,7 @@ gnus-update-marks
 	(gnus-request-set-mark gnus-newsgroup-name delta-marks))
 
       ;; Enter these new marks into the info of the group.
-      (if (nthcdr 3 info)
-	  (setcar (nthcdr 3 info) newmarked)
-	;; Add the marks lists to the end of the info.
-	(when newmarked
-	  (setcdr (nthcdr 2 info) (list newmarked))))
-
-      ;; Cut off the end of the info if there's nothing else there.
-      (let ((i 5))
-	(while (and (> i 2)
-		    (not (nth i info)))
-	  (when (nthcdr (cl-decf i) info)
-	    (setcdr (nthcdr i info) nil)))))))
+      (setf (gnus-info-marks info) newmarked))))
 
 (defun gnus-set-mode-line (where)
   "Set the mode line of the article or summary buffers.
@@ -6278,7 +6267,7 @@ gnus-create-xref-hashtb
 (defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads)
   "Look through all the headers and mark the Xrefs as read."
   (let ((virtual (gnus-virtual-group-p from-newsgroup))
-	info xref-hashtb method nth4)
+	info xref-hashtb method tmp-method)
     (with-current-buffer gnus-group-buffer
       (when (setq xref-hashtb
 		  (gnus-create-xref-hashtb from-newsgroup headers unreads))
@@ -6288,17 +6277,18 @@ gnus-mark-xrefs-as-read
 	     ;; Dead groups are not updated.
 	     (and (prog1
 		      (setq info (gnus-get-info group))
-		    (when (stringp (setq nth4 (gnus-info-method info)))
-		      (setq nth4 (gnus-server-to-method nth4))))
+		    (when (stringp (setq tmp-method (gnus-info-method info)))
+		      (setq tmp-method (gnus-server-to-method tmp-method))))
 		  ;; Only do the xrefs if the group has the same
 		  ;; select method as the group we have just read.
 		  (or (gnus-methods-equal-p
-		       nth4 (gnus-find-method-for-group from-newsgroup))
+		       tmp-method (gnus-find-method-for-group from-newsgroup))
 		      virtual
-		      (equal nth4 (setq method (gnus-find-method-for-group
-						from-newsgroup)))
-		      (and (equal (car nth4) (car method))
-			   (equal (nth 1 nth4) (nth 1 method))))
+		      (equal tmp-method
+			     (setq method (gnus-find-method-for-group
+					   from-newsgroup)))
+		      (and (equal (car tmp-method) (car method))
+			   (equal (nth 1 tmp-method) (nth 1 method))))
 		  gnus-use-cross-reference
 		  (or (not (eq gnus-use-cross-reference t))
 		      virtual
@@ -6310,7 +6300,7 @@ gnus-mark-xrefs-as-read
 
 (defun gnus-compute-read-articles (group articles)
   (let* ((entry (gnus-group-entry group))
-	 (info (nth 1 entry))
+	 (info (gnus-get-info entry))
 	 (active (gnus-active group))
 	 ninfo)
     (when entry
@@ -6347,7 +6337,7 @@ gnus-group-make-articles-read
   "Update the info of GROUP to say that ARTICLES are read."
   (let* ((num 0)
 	 (entry (gnus-group-entry group))
-	 (info (nth 1 entry))
+	 (info (gnus-get-info entry))
 	 (active (gnus-active group))
 	 (set-marks
 	  (gnus-method-option-p
@@ -6367,7 +6357,7 @@ gnus-group-make-articles-read
 	(gnus-undo-register
 	  `(progn
 	     (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-	     (gnus-info-set-read ',info ',(gnus-info-read info))
+	     (setf (gnus-info-read ',info) ',(gnus-info-read info))
 	     (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
 	     (when ,set-marks
 	       (gnus-request-set-mark
@@ -6375,7 +6365,7 @@ gnus-group-make-articles-read
 	     (gnus-group-jump-to-group ,group)
 	     (gnus-group-update-group ,group t))))
       ;; Add the read articles to the range.
-      (gnus-info-set-read info range)
+      (setf (gnus-info-read info) range)
       (when set-marks
 	(gnus-request-set-mark group (list (list range 'add '(read)))))
       ;; Then we have to re-compute how many unread
@@ -6395,7 +6385,7 @@ gnus-group-make-articles-read
 	    (setq range (cdr range)))
 	  (setq num (- (cdr active) num))))
 	;; Update the number of unread articles.
-	(setcar entry num)
+	(setf (gnus-group-unread group) num)
 	;; Update the group buffer.
 	(unless (gnus-ephemeral-group-p group)
 	  (gnus-group-update-group group t))))))
@@ -10283,8 +10273,8 @@ gnus-summary-move-article
 	    (when (and (not (memq article gnus-newsgroup-unreads))
 		       (cdr art-group))
 	      (push 'read to-marks)
-	      (gnus-info-set-read
-	       info (gnus-add-to-range (gnus-info-read info)
+	      (setf (gnus-info-read info)
+		    (gnus-add-to-range (gnus-info-read info)
 				       (list (cdr art-group)))))
 
 	    ;; See whether the article is to be put in the cache.
@@ -12894,15 +12884,16 @@ gnus-update-read-articles
 	    (set-buffer gnus-group-buffer)
 	    (gnus-undo-register
 	      `(progn
+		 ;;FIXME: A better way of ensuring info completness?
 		 (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-		 (gnus-info-set-read ',info ',(gnus-info-read info))
+		 (setf (gnus-info-read ',info) ',(gnus-info-read info))
 		 (gnus-group-jump-to-group ,group)
 		 (gnus-get-unread-articles-in-group ',info
 						    (gnus-active ,group))
 		 (gnus-group-update-group ,group t)
 		 ,setmarkundo))))
 	;; Enter this list into the group info.
-	(gnus-info-set-read info read)
+	(setf (gnus-info-read info) read)
 	;; Set the number of unread articles in gnus-newsrc-hashtb.
 	(gnus-get-unread-articles-in-group info (gnus-active group))
 	t))))
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 0673ac15f6..392a4e8812 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -2815,20 +2815,37 @@ gnus-set-active
   "Set GROUP's active info."
   `(puthash ,group ,active gnus-active-hashtb))
 
-;; Info access macros.
-
-(defmacro gnus-info-group (info)
-  `(nth 0 ,info))
-(defmacro gnus-info-rank (info)
-  `(nth 1 ,info))
-(defmacro gnus-info-read (info)
-  `(nth 2 ,info))
-(defmacro gnus-info-marks (info)
-  `(nth 3 ,info))
-(defmacro gnus-info-method (info)
-  `(nth 4 ,info))
-(defmacro gnus-info-params (info)
-  `(nth 5 ,info))
+;; Info definition.
+
+(cl-defstruct (gnus-info
+	       (:copier nil)
+	       (:constructor make-gnus-info
+			     (group rank read &optional marks method params))
+	       (:type list))
+  "A structure holding information about a Gnus group."
+  (group ""
+	 :type string
+	 :documentation "The group name of this info.")
+  (rank `,gnus-level-default-subscribed
+	:type (or integer cons)
+	:documentation "The rank of this group.  Either a single
+        integer indicating the level of subscribedness, or a cons
+        of (LEVEL . SCORE).")
+  (read nil
+	:type list
+	:documentation "A range of read articles in this group.")
+  (marks nil
+	 :type list
+	 :documentation "An alist of marks (as symbols) mapped to
+	 ranges of articles that have those marks.")
+  (method nil
+	  :type list
+	  :documentation "This group's server method.  Typically
+	  a list of (TYPE ADDRESS), where TYPE is a backend
+	  symbol and ADDRESS is a string adress.")
+  (params nil
+	  :type list
+	  :documentation "An alist of group parameters."))
 
 (defmacro gnus-info-level (info)
   `(let ((rank (gnus-info-rank ,info)))
@@ -2839,49 +2856,55 @@ gnus-info-score
   `(let ((rank (gnus-info-rank ,info)))
      (or (and (consp rank) (cdr rank)) 0)))
 
+;; These setters are mostly here for backwards compatibility.
+
 (defmacro gnus-info-set-group (info group)
-  `(setcar ,info ,group))
+  `(setf (gnus-info-group ,info) ,group))
+
 (defmacro gnus-info-set-rank (info rank)
-  `(setcar (nthcdr 1 ,info) ,rank))
+  `(setf (gnus-info-rank ,info) ,rank))
+
 (defmacro gnus-info-set-read (info read)
-  `(setcar (nthcdr 2 ,info) ,read))
-(defmacro gnus-info-set-marks (info marks &optional extend)
-  (if extend
-      `(gnus-info-set-entry ,info ,marks 3)
-    `(setcar (nthcdr 3 ,info) ,marks)))
-(defmacro gnus-info-set-method (info method &optional extend)
-  (if extend
-      `(gnus-info-set-entry ,info ,method 4)
-    `(setcar (nthcdr 4 ,info) ,method)))
-(defmacro gnus-info-set-params (info params &optional extend)
-  (if extend
-      `(gnus-info-set-entry ,info ,params 5)
-    `(setcar (nthcdr 5 ,info) ,params)))
-
-(defun gnus-info-set-entry (info entry number)
-  ;; Extend the info until we have enough elements.
-  (while (<= (length info) number)
-    (nconc info (list nil)))
-  ;; Set the entry.
-  (setcar (nthcdr number info) entry))
+  `(setf (gnus-info-read ,info) ,read))
+
+(defmacro gnus-info-set-marks (info marks &optional _extend)
+  `(setf (gnus-info-marks ,info) ,marks))
+
+(defmacro gnus-info-set-method (info method &optional _extend)
+  `(setf (gnus-info-method ,info) ,method))
+
+(defmacro gnus-info-set-params (info params &optional _extend)
+  `(setf (gnus-info-params ,info) ,params))
 
 (defmacro gnus-info-set-level (info level)
-  `(let ((rank (cdr ,info)))
-     (if (consp (car rank))
-	 (setcar (car rank) ,level)
-       (setcar rank ,level))))
+  `(let ((rank (gnus-info-rank ,info)))
+     (if (consp rank)
+	 (setcar (gnus-info-rank ,info) ,level)
+       (setf (gnus-info-rank ,info) ,level))))
+
 (defmacro gnus-info-set-score (info score)
-  `(let ((rank (cdr ,info)))
-     (if (consp (car rank))
-	 (setcdr (car rank) ,score)
-       (setcar rank (cons (car rank) ,score)))))
+  `(let ((rank (gnus-info-rank ,info)))
+     (if (consp rank)
+	 (setcdr (gnus-info-rank ,info) ,score)
+       (setf (gnus-info-rank ,info) (cons rank ,score)))))
 
 (defmacro gnus-get-info (group)
   `(nth 1 (gethash ,group gnus-newsrc-hashtb)))
 
 (defun gnus-set-info (group info)
-  (setcdr (gethash group gnus-newsrc-hashtb)
-	  (list info)))
+  (let ((entry (cdr (gethash group gnus-newsrc-hashtb))))
+    ;; Set individual elements of the info so as not to break object
+    ;; reference.
+    (setf (gnus-info-rank entry)
+	  (gnus-info-rank info))
+    (setf (gnus-info-read entry)
+	  (gnus-info-read info))
+    (setf (gnus-info-marks entry)
+	  (gnus-info-marks info))
+    (setf (gnus-info-method entry)
+	  (gnus-info-method info))
+    (setf (gnus-info-params entry)
+	  (gnus-info-params info))))
 
 
 ;;;
@@ -3689,7 +3712,7 @@ gnus-group-set-parameter
 	    (setq new-params (append new-params (list (car old-params)))))
 	  (setq old-params (cdr old-params)))
 	(if (listp group)
-	    (gnus-info-set-params info new-params t)
+	    (setf (gnus-info-params info) new-params)
 	  (gnus-group-set-info new-params (gnus-info-group info) 'params))))))
 
 (defun gnus-group-remove-parameter (group name)
@@ -3704,14 +3727,15 @@ gnus-group-remove-parameter
 	  (setq params (delq name params))
 	  (while (assq name params)
 	    (gnus-alist-pull name params))
-	  (gnus-info-set-params info params))))))
+	  (setf (gnus-info-params info) params))))))
 
 (defun gnus-group-add-score (group &optional score)
   "Add SCORE to the GROUP score.
 If SCORE is nil, add 1 to the score of GROUP."
   (let ((info (gnus-get-info group)))
     (when info
-      (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
+      (setf (gnus-info-score info)
+	    (+ (gnus-info-score info) (or score 1))))))
 
 (defun gnus-short-group-name (group &optional levels)
   "Collapse GROUP name LEVELS.
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index f79d8f1707..88bb5651e2 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -795,8 +795,9 @@ nndiary-request-update-info
 	  (kill-buffer buf))
 	(setq unread (sort unread '<))
 	(and unread
-	     (gnus-info-set-read info (gnus-update-read-articles
-				       (gnus-info-group info) unread t)))
+	     (setf (gnus-info-read info)
+		   (gnus-update-read-articles
+		    (gnus-info-group info) unread t)))
 	))
     (run-hook-with-args 'nndiary-request-update-info-functions
 			(gnus-info-group info))
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index bc475ee295..cc9923164a 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -147,17 +147,17 @@ nndraft-request-restore-buffer
 
 (deffoo nndraft-request-update-info (group info &optional server)
   (nndraft-possibly-change-group group)
-  (gnus-info-set-read
-   info
-   (gnus-update-read-articles (gnus-group-prefixed-name group '(nndraft ""))
-			      (nndraft-articles) t))
-  (let ((marks (nth 3 info)))
+  (setf (gnus-info-read info)
+	(gnus-update-read-articles
+	 (gnus-group-prefixed-name group '(nndraft ""))
+	 (nndraft-articles) t))
+  (let ((marks (gnus-info-marks info)))
     (when marks
       ;; Nix out all marks except the `unsend'-able article marks.
-      (setcar (nthcdr 3 info)
-	      (if (assq 'unsend marks)
-		  (list (assq 'unsend marks))
-		nil))))
+      (setf (gnus-info-marks info)
+	    (if (assq 'unsend marks)
+		(list (assq 'unsend marks))
+	      nil))))
   t)
 
 (defun nndraft-generate-headers ()
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 856ac75cd6..98be27fc74 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1620,7 +1620,7 @@ nnimap-update-info
 		       read)))
 	      (when (or (not (listp permanent-flags))
 			(memq '%Seen permanent-flags))
-		(gnus-info-set-read info read))
+		(setf (gnus-info-read info) read))
 	      ;; Update the marks.
 	      (setq marks (gnus-info-marks info))
 	      (dolist (type (cdr nnimap-mark-alist))
@@ -1663,7 +1663,7 @@ nnimap-update-info
 		(if old-unexists
 		    (setcdr old-unexists unexists)
 		  (push (cons 'unexist unexists) marks)))
-	      (gnus-info-set-marks info marks t))))
+	      (setf (gnus-info-marks info) marks))))
 	;; Tell Gnus whether there are any \Recent messages in any of
 	;; the groups.
 	(let ((recent (cdr (assoc '%Recent flags))))
@@ -1680,14 +1680,13 @@ nnimap-update-info
 
 (defun nnimap-update-qresync-info (info existing vanished flags)
   ;; Add all the vanished articles to the list of read articles.
-  (gnus-info-set-read
-   info
-   (gnus-add-to-range
-    (gnus-add-to-range
-     (gnus-range-add (gnus-info-read info)
-		     vanished)
-     (cdr (assq '%Flagged flags)))
-    (cdr (assq '%Seen flags))))
+  (setf (gnus-info-read info)
+	(gnus-add-to-range
+	 (gnus-add-to-range
+	  (gnus-range-add (gnus-info-read info)
+			  vanished)
+	  (cdr (assq '%Flagged flags)))
+	 (cdr (assq '%Seen flags))))
   (let ((marks (gnus-info-marks info)))
     (dolist (type (cdr nnimap-mark-alist))
       (let ((ticks (assoc (car type) marks))
@@ -1707,7 +1706,7 @@ nnimap-update-qresync-info
 			(gnus-sorted-complement existing new-marks))))
 	  (when ticks
 	    (push (cons (car type) ticks) marks))
-	  (gnus-info-set-marks info marks t))))
+	  (setf (gnus-info-marks info) marks))))
     ;; Add vanished to the list of unexisting articles.
     (when vanished
       (let* ((old-unexists (assq 'unexist marks))
@@ -1715,7 +1714,7 @@ nnimap-update-qresync-info
 	(if old-unexists
 	    (setcdr old-unexists unexists)
 	  (push (cons 'unexist unexists) marks)))
-      (gnus-info-set-marks info marks t))))
+      (setf (gnus-info-marks info) marks))))
 
 (defun nnimap-imap-ranges-to-gnus-ranges (irange)
   (if (zerop (length irange))
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 7cb2d1615a..45fbadf23c 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -874,8 +874,8 @@ nnir-request-set-mark
 (deffoo nnir-request-update-info (group info &optional server)
   (nnir-possibly-change-group group server)
   ;; clear out all existing marks.
-  (gnus-info-set-marks info nil)
-  (gnus-info-set-read info nil)
+  (setf (gnus-info-marks info) nil)
+  (setf (gnus-info-read info) nil)
   (let ((group (gnus-group-guess-full-name-from-command-method group))
 	(articles-by-group
 	 (nnir-categorize
@@ -889,8 +889,8 @@ nnir-request-update-info
 	     (group-info (gnus-get-info (car group-articles)))
 	     (marks (gnus-info-marks group-info))
 	     (read (gnus-info-read group-info)))
-	(gnus-info-set-read
-	 info
+	(setf
+	 (gnus-info-read info)
 	 (gnus-add-to-range
 	  (gnus-info-read info)
 	  (delq nil
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 0133fc6ce2..fdb487d076 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -1000,8 +1000,8 @@ nnmaildir-request-update-info
 	    pgname (nnmaildir--pgname nnmaildir--cur-server gname)
 	    flist (nnmaildir--grp-flist group))
       (when (zerop (nnmaildir--grp-count group))
-	(gnus-info-set-read info nil)
-	(gnus-info-set-marks info nil 'extend)
+	(setf (gnus-info-read info) nil
+	      (gnus-info-marks info) nil)
 	(throw 'return info))
       (setq old-marks (cons 'read (gnus-info-read info))
 	    old-marks (cons old-marks (gnus-info-marks info))
@@ -1083,9 +1083,9 @@ nnmaildir-request-update-info
 	    (setq ranges (gnus-add-to-range ranges (sort article-list '<)))))
 	(if (eq mark 'read) (setq read ranges)
 	  (if ranges (setq marks (cons (cons mark ranges) marks)))))
-      (gnus-info-set-read info (gnus-range-add read missing))
-      (gnus-info-set-marks info marks 'extend)
-      (setf (nnmaildir--grp-mmth group) new-mmth)
+      (setf (gnus-info-read info) (gnus-range-add read missing)
+	    (gnus-info-marks info) marks
+	    (nnmaildir--grp-mmth group) new-mmth)
       info)))
 
 (defun nnmaildir-request-group (gname &optional server fast _info)
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index 6c5502ac3d..722cb95306 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -711,29 +711,27 @@ nnmairix-request-marks
 	    (nnimap-request-update-info-internal folder folderinfo nnmairix-backend-server)
 	  (nnmairix-call-backend "request-update-info" folder folderinfo nnmairix-backend-server))
 	;; set range of read articles
-	(gnus-info-set-read
-	 info
-	 (if docorr
-	     (nnmairix-map-range
-	      `(lambda (x) (+ x ,(cadr corr)))
-	      (gnus-info-read folderinfo))
-	   (gnus-info-read folderinfo)))
+	(setf (gnus-info-read info)
+	      (if docorr
+		  (nnmairix-map-range
+		   `(lambda (x) (+ x ,(cadr corr)))
+		   (gnus-info-read folderinfo))
+		(gnus-info-read folderinfo)))
 	;; set other marks
-	(gnus-info-set-marks
-	 info
-	 (if docorr
-	     (mapcar (lambda (cur)
-			 (cons
-			  (car cur)
-			  (nnmairix-map-range
-			   `(lambda (x) (+ x ,(cadr corr)))
-			   (list (cadr cur)))))
-		     (gnus-info-marks folderinfo))
-	   (gnus-info-marks folderinfo))))
+	(setf (gnus-info-marks info)
+	      (if docorr
+		  (mapcar (lambda (cur)
+			    (cons
+			     (car cur)
+			     (nnmairix-map-range
+			      `(lambda (x) (+ x ,(cadr corr)))
+			      (list (cadr cur)))))
+			  (gnus-info-marks folderinfo))
+		(gnus-info-marks folderinfo))))
       (when (eq readmarks 'unread)
-	(gnus-info-set-read info nil))
+	(setf (gnus-info-read info) nil))
       (when (eq readmarks 'read)
-	(gnus-info-set-read info (gnus-active qualgroup))))
+	(setf (gnus-info-read info) (gnus-active qualgroup))))
   t)
 
 (nnoo-define-skeleton nnmairix)
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 302589bd6d..8d8d5ae83a 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1067,7 +1067,7 @@ nnml-request-compact-group
 		  (when (gnus-member-of-range old-number read)
 		    (setq read (gnus-remove-from-range read (list old-number)))
 		    (setq read (gnus-add-to-range read (list new-number))))
-		  (gnus-info-set-read info read))
+		  (setf (gnus-info-read info) read))
 		;; 2 b/ marked articles:
 		(let ((oldmarks (gnus-info-marks info))
 		      mark newmarks)
@@ -1080,7 +1080,7 @@ nnml-request-compact-group
 		      (setcdr mark (gnus-add-to-range (cdr mark)
 						      (list new-number))))
 		    (push mark newmarks))
-		  (gnus-info-set-marks info newmarks))
+		  (setf (gnus-info-marks info) newmarks))
 		;; 3/ Update the NOV entry for this article:
 		(unless nnml-nov-is-evil
 		  (with-current-buffer (nnml-open-nov group)
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index 25f3413fcd..0a4d33cfab 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -307,11 +307,9 @@ nnvirtual-request-update-info
     ;; Install the precomputed lists atomically, so the virtual group
     ;; is not left in a half-way state in case of C-g.
     (gnus-atomic-progn
-      (setcar (cddr info) nnvirtual-mapping-reads)
-      (if (nthcdr 3 info)
-	  (setcar (nthcdr 3 info) nnvirtual-mapping-marks)
-	(when nnvirtual-mapping-marks
-	  (setcdr (nthcdr 2 info) (list nnvirtual-mapping-marks))))
+      (setf (gnus-info-read info) nnvirtual-mapping-reads)
+      (when nnvirtual-mapping-marks
+	(setf (gnus-info-marks info) nnvirtual-mapping-marks))
       (setq nnvirtual-info-installed t))
     t))
 
@@ -463,11 +461,10 @@ nnvirtual-update-read-and-marked
 	(dolist (group nnvirtual-component-groups)
 	  (when (and (setq info (gnus-get-info group))
 		     (gnus-info-marks info))
-	    (gnus-info-set-marks
-	     info
-	     (if (assq 'score (gnus-info-marks info))
-		 (list (assq 'score (gnus-info-marks info)))
-	       nil))))
+	    (setf (gnus-info-marks info)
+		  (if (assq 'score (gnus-info-marks info))
+		      (list (assq 'score (gnus-info-marks info)))
+		    nil))))
 
 	;; Ok, currently type-marks is an assq list with keys of a mark type,
 	;; with data of an assq list with keys of component group names
-- 
2.23.0


--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at 38000 <at> debbugs.gnu.org:


Received: (at 38000) by debbugs.gnu.org; 1 Nov 2019 18:07:16 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Nov 01 14:07:16 2019
Received: from localhost ([127.0.0.1]:57077 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQbKL-00088B-MN
	for submit <at> debbugs.gnu.org; Fri, 01 Nov 2019 14:07:13 -0400
Received: from ericabrahamsen.net ([52.70.2.18]:40062
 helo=mail.ericabrahamsen.net)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <eric@HIDDEN>) id 1iQbKK-00087t-MG
 for 38000 <at> debbugs.gnu.org; Fri, 01 Nov 2019 14:07:13 -0400
Received: from localhost (c-73-254-86-141.hsd1.wa.comcast.net [73.254.86.141])
 (Authenticated sender: eric@HIDDEN)
 by mail.ericabrahamsen.net (Postfix) with ESMTPSA id 4C9BBFA07E;
 Fri,  1 Nov 2019 18:07:05 +0000 (UTC)
From: Eric Abrahamsen <eric@HIDDEN>
To: Lars Ingebrigtsen <larsi@HIDDEN>
Subject: Re: bug#38000: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN> <87ftj9m7q4.fsf@HIDDEN>
 <8736f8bu7r.fsf@HIDDEN> <87v9s33e3s.fsf@HIDDEN>
Date: Fri, 01 Nov 2019 11:07:03 -0700
In-Reply-To: <87v9s33e3s.fsf@HIDDEN> (Lars Ingebrigtsen's message of "Fri,
 01 Nov 2019 14:44:55 +0100")
Message-ID: <877e4jlbco.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: 38000
Cc: 38000 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

Lars Ingebrigtsen <larsi@HIDDEN> writes:

> Eric Abrahamsen <eric@HIDDEN> writes:
>
>> Huh, I didn't realize that list-based structs didn't put a tag in the
>> `car' position unless you pass the :named keyword.
>>
>> We could switch to list-based structs without breaking out-of-tree code,
>> but I don't see much point: you can't use them for generic function
>> dispatch, even when they're :named, nor do you get a NAME-p predicate
>> for free. That doesn't leave much point.
>
> It means that you don't have to write the accessor macros by hand.  :-)

But you already did! :)

Okay, let's use them anyway. And I'd like to move the "extend" and
"vacuum" procedures to the reading and writing of the newsrc.eld file,
so the rest of the code can forget about it. I'll leave the setter
macros in place, and continue to accept (and ignore) an EXTEND argument,
so other people's code continues to work.

>> Nope, still don't get it. It seems to me the only real question is
>> whether or not nnvirtual-mapping-marks should override whatever marks
>> were already there.
>
> I don't get it either, I'm afraid.

I'll look at it some more, and see if I can come up with some tests.

Eric




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at 38000 <at> debbugs.gnu.org:


Received: (at 38000) by debbugs.gnu.org; 1 Nov 2019 13:45:01 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Nov 01 09:45:01 2019
Received: from localhost ([127.0.0.1]:55227 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQXEb-0000sq-DF
	for submit <at> debbugs.gnu.org; Fri, 01 Nov 2019 09:45:01 -0400
Received: from quimby.gnus.org ([80.91.231.51]:36112)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <larsi@HIDDEN>) id 1iQXEa-0000sj-Db
 for 38000 <at> debbugs.gnu.org; Fri, 01 Nov 2019 09:45:00 -0400
Received: from cm-84.212.202.86.getinternet.no ([84.212.202.86] helo=marnie)
 by quimby.gnus.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.89) (envelope-from <larsi@HIDDEN>)
 id 1iQXEW-0006Mb-Fg; Fri, 01 Nov 2019 14:44:58 +0100
From: Lars Ingebrigtsen <larsi@HIDDEN>
To: Eric Abrahamsen <eric@HIDDEN>
Subject: Re: bug#38000: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN> <87ftj9m7q4.fsf@HIDDEN>
 <8736f8bu7r.fsf@HIDDEN>
Date: Fri, 01 Nov 2019 14:44:55 +0100
In-Reply-To: <8736f8bu7r.fsf@HIDDEN> (Eric Abrahamsen's message of
 "Thu, 31 Oct 2019 12:17:28 -0700")
Message-ID: <87v9s33e3s.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org",
 has NOT identified this incoming email as spam.  The original
 message has been attached to this so you can view it or label
 similar future email.  If you have any questions, see
 @@CONTACT_ADDRESS@@ for details.
 Content preview:  Eric Abrahamsen <eric@HIDDEN> writes: > Huh, I
 didn't realize that list-based structs didn't put a tag in the > `car'
 position
 unless you pass the :named keyword. > > We could switch to list-based structs
 without breaking out-of-tree code [...] 
 Content analysis details:   (-2.9 points, 5.0 required)
 pts rule name              description
 ---- ---------------------- --------------------------------------------------
 -1.0 ALL_TRUSTED            Passed through trusted hosts only via SMTP
 -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
 [score: 0.0000]
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 38000
Cc: 38000 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Eric Abrahamsen <eric@HIDDEN> writes:

> Huh, I didn't realize that list-based structs didn't put a tag in the
> `car' position unless you pass the :named keyword.
>
> We could switch to list-based structs without breaking out-of-tree code,
> but I don't see much point: you can't use them for generic function
> dispatch, even when they're :named, nor do you get a NAME-p predicate
> for free. That doesn't leave much point.

It means that you don't have to write the accessor macros by hand.  :-)

> Nope, still don't get it. It seems to me the only real question is
> whether or not nnvirtual-mapping-marks should override whatever marks
> were already there.

I don't get it either, I'm afraid.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at 38000 <at> debbugs.gnu.org:


Received: (at 38000) by debbugs.gnu.org; 31 Oct 2019 19:17:39 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Oct 31 15:17:39 2019
Received: from localhost ([127.0.0.1]:54324 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQFwx-0008Ai-7O
	for submit <at> debbugs.gnu.org; Thu, 31 Oct 2019 15:17:39 -0400
Received: from ericabrahamsen.net ([52.70.2.18]:59952
 helo=mail.ericabrahamsen.net)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <eric@HIDDEN>) id 1iQFwu-0008AQ-Ml
 for 38000 <at> debbugs.gnu.org; Thu, 31 Oct 2019 15:17:37 -0400
Received: from localhost (c-73-254-86-141.hsd1.wa.comcast.net [73.254.86.141])
 (Authenticated sender: eric@HIDDEN)
 by mail.ericabrahamsen.net (Postfix) with ESMTPSA id 0751BFA07E;
 Thu, 31 Oct 2019 19:17:29 +0000 (UTC)
From: Eric Abrahamsen <eric@HIDDEN>
To: Lars Ingebrigtsen <larsi@HIDDEN>
Subject: Re: bug#38000: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN> <87ftj9m7q4.fsf@HIDDEN>
Date: Thu, 31 Oct 2019 12:17:28 -0700
Message-ID: <8736f8bu7r.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: 38000
Cc: 38000 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

Lars Ingebrigtsen <larsi@HIDDEN> writes:

> Eric Abrahamsen <eric@HIDDEN> writes:
>
>> The attached patch is a work-in-progress for making sure that all of
>> Gnus' code only accesses group infos via the relevant macros --
>> essentially hiding the fact that group infos are implemented as lists,
>> in anticipation of eventually being able to re-implement them as structs
>> at some point in the future.
>>
>> Essentially, "(nth 3 info)" becomes "(gnus-info-marks info)", and so
>> one.
>>
>> It also replaces uses of "gnus-info-set-*" with "(setf (gnus-info-* ".
>> The setter macros aren't deprecated, though.
>
> Sounds good, but you can do this with the cl-defstruct list thing
> already without changing what the data is.
>
> (cl-defstruct (gnus-info
>                (:constructor make-gnus-info)
>                (:copier nil)
>                (:type list))
>  (group ...))
>
> Actually changing the data format itself I'm not very enthusiastic
> about.  There's tons of out-of-tree code that would break.

Huh, I didn't realize that list-based structs didn't put a tag in the
`car' position unless you pass the :named keyword.

We could switch to list-based structs without breaking out-of-tree code,
but I don't see much point: you can't use them for generic function
dispatch, even when they're :named, nor do you get a NAME-p predicate
for free. That doesn't leave much point.

I think we can just stick with hiding the implementation for now,
encourage other developers not to use `nth', and maybe someday in the
future switch to record-based structs.

>> If I could understand why _some_ of the infos are expected to be short a
>> few elements (newly-created groups?), I would rather provide a
>> `make-gnus-info' function (again, in anticipation of a struct
>> constructor), which could be called with the elements of an info (either
>> as a list or spread) and return an info filled-out with nils where
>> necessary. Then that could be used wherever we expect a short info.
>
> I think it's just because the data is written to .newsrc.eld as is, and
> writing a bunch of nils there would make the file a lot bigger.
> Remember, people may have thousands of groups.

Okay, maybe all that stuff should just stay as it is, then. Alternately,
I could do something fancy with gv-setters for `gnus-info-marks' et al,
so that setting them via `setf' would first ensure their length.

Alternately, we could pad out each info as it is read from .newsrc.eld,
and vacuum out nils again before it is written. Then the rest of the
code could just forget about it.

>> One last bit I'm uncertain about is in `nnvirtual-request-update-info',
>> where I've replaced this:
>>
>>       (setcar (cddr info) nnvirtual-mapping-reads)
>>       (if (nthcdr 3 info)
>> 	  (setcar (nthcdr 3 info) nnvirtual-mapping-marks)
>> 	(when nnvirtual-mapping-marks
>> 	  (setcdr (nthcdr 2 info) (list nnvirtual-mapping-marks))))
>>
>> with this:
>>
>>       (setf (gnus-info-read info) nnvirtual-mapping-reads)
>>       (when nnvirtual-mapping-marks
>> 	(setf (gnus-info-marks info) nnvirtual-mapping-marks))
>>
>> It seems to work fine, but to be honest I don't really understand the
>> original logic.
>
> I don't understand it either, but it's setting both the second and the
> fourth slot, isn't it?

I'm pretty sure the first line (setting the read slot) is correct.

Then the if statement... "if the info has marks or method or params, set
the marks to nnvirtual-mapping-marks, regardless of whether
nnvirtual-mapping-marks is nil or not, and overwriting whatever the
marks were before. Otherwise, if the info has no marks and
nnvirtual-mapping-marks is non-nil, set the info marks to
nnvirtual-mapping-marks."

Nope, still don't get it. It seems to me the only real question is
whether or not nnvirtual-mapping-marks should override whatever marks
were already there.

Eric




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 31 Oct 2019 12:15:47 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Oct 31 08:15:47 2019
Received: from localhost ([127.0.0.1]:52195 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iQ9Mf-0006Qw-1Q
	for submit <at> debbugs.gnu.org; Thu, 31 Oct 2019 08:15:47 -0400
Received: from lists.gnu.org ([209.51.188.17]:53147)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <larsi@HIDDEN>) id 1iQ9Mc-0006Qo-So
 for submit <at> debbugs.gnu.org; Thu, 31 Oct 2019 08:15:43 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10]:55407)
 by lists.gnu.org with esmtp (Exim 4.90_1)
 (envelope-from <larsi@HIDDEN>) id 1iQ9Ma-0003WI-FY
 for bug-gnu-emacs@HIDDEN; Thu, 31 Oct 2019 08:15:42 -0400
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org
X-Spam-Level: 
X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,URIBL_BLOCKED
 autolearn=disabled version=3.3.2
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
 (envelope-from <larsi@HIDDEN>) id 1iQ9MY-00017x-GE
 for bug-gnu-emacs@HIDDEN; Thu, 31 Oct 2019 08:15:40 -0400
Received: from quimby.gnus.org ([80.91.231.51]:39120)
 by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
 (Exim 4.71) (envelope-from <larsi@HIDDEN>) id 1iQ9MX-00014R-4z
 for bug-gnu-emacs@HIDDEN; Thu, 31 Oct 2019 08:15:38 -0400
Received: from cm-84.212.202.86.getinternet.no ([84.212.202.86] helo=marnie)
 by quimby.gnus.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.89) (envelope-from <larsi@HIDDEN>)
 id 1iQ9MS-0008U3-Dh; Thu, 31 Oct 2019 13:15:34 +0100
From: Lars Ingebrigtsen <larsi@HIDDEN>
To: Eric Abrahamsen <eric@HIDDEN>
Subject: Re: 27.0.50; [PATCH] WIP on using gnus info accessor macros
References: <875zk5aipv.fsf@HIDDEN>
Date: Thu, 31 Oct 2019 13:15:31 +0100
In-Reply-To: <875zk5aipv.fsf@HIDDEN> (Eric Abrahamsen's message of
 "Wed, 30 Oct 2019 16:58:52 -0700")
Message-ID: <87ftj9m7q4.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]
 [fuzzy]
X-Received-From: 80.91.231.51
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: submit
Cc: bug-gnu-emacs@HIDDEN
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

Eric Abrahamsen <eric@HIDDEN> writes:

> The attached patch is a work-in-progress for making sure that all of
> Gnus' code only accesses group infos via the relevant macros --
> essentially hiding the fact that group infos are implemented as lists,
> in anticipation of eventually being able to re-implement them as structs
> at some point in the future.
>
> Essentially, "(nth 3 info)" becomes "(gnus-info-marks info)", and so
> one.
>
> It also replaces uses of "gnus-info-set-*" with "(setf (gnus-info-* ".
> The setter macros aren't deprecated, though.

Sounds good, but you can do this with the cl-defstruct list thing
already without changing what the data is.

(cl-defstruct (gnus-info
               (:constructor make-gnus-info)
               (:copier nil)
               (:type list))
 (group ...))

Actually changing the data format itself I'm not very enthusiastic
about.  There's tons of out-of-tree code that would break.

> If I could understand why _some_ of the infos are expected to be short a
> few elements (newly-created groups?), I would rather provide a
> `make-gnus-info' function (again, in anticipation of a struct
> constructor), which could be called with the elements of an info (either
> as a list or spread) and return an info filled-out with nils where
> necessary. Then that could be used wherever we expect a short info.

I think it's just because the data is written to .newsrc.eld as is, and
writing a bunch of nils there would make the file a lot bigger.
Remember, people may have thousands of groups.

> One last bit I'm uncertain about is in `nnvirtual-request-update-info',
> where I've replaced this:
>
>       (setcar (cddr info) nnvirtual-mapping-reads)
>       (if (nthcdr 3 info)
> 	  (setcar (nthcdr 3 info) nnvirtual-mapping-marks)
> 	(when nnvirtual-mapping-marks
> 	  (setcdr (nthcdr 2 info) (list nnvirtual-mapping-marks))))
>
> with this:
>
>       (setf (gnus-info-read info) nnvirtual-mapping-reads)
>       (when nnvirtual-mapping-marks
> 	(setf (gnus-info-marks info) nnvirtual-mapping-marks))
>
> It seems to work fine, but to be honest I don't really understand the
> original logic.

I don't understand it either, but it's setting both the second and the
fourth slot, isn't it?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 30 Oct 2019 23:59:15 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Oct 30 19:59:15 2019
Received: from localhost ([127.0.0.1]:51910 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1iPxrt-0007SG-Pt
	for submit <at> debbugs.gnu.org; Wed, 30 Oct 2019 19:59:15 -0400
Received: from lists.gnu.org ([209.51.188.17]:55104)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <eric@HIDDEN>) id 1iPxrq-0007S5-U2
 for submit <at> debbugs.gnu.org; Wed, 30 Oct 2019 19:59:12 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10]:53742)
 by lists.gnu.org with esmtp (Exim 4.90_1)
 (envelope-from <eric@HIDDEN>) id 1iPxrm-0008KB-I7
 for bug-gnu-emacs@HIDDEN; Wed, 30 Oct 2019 19:59:10 -0400
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org
X-Spam-Level: 
X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_50,RCVD_IN_DNSWL_MED,
 URIBL_BLOCKED autolearn=disabled version=3.3.2
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
 (envelope-from <eric@HIDDEN>) id 1iPxri-00031S-9Z
 for bug-gnu-emacs@HIDDEN; Wed, 30 Oct 2019 19:59:06 -0400
Received: from ericabrahamsen.net ([52.70.2.18]:33026
 helo=mail.ericabrahamsen.net)
 by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)
 (Exim 4.71) (envelope-from <eric@HIDDEN>)
 id 1iPxri-0002vr-0k
 for bug-gnu-emacs@HIDDEN; Wed, 30 Oct 2019 19:59:02 -0400
Received: from localhost (unknown [205.175.106.86])
 (Authenticated sender: eric@HIDDEN)
 by mail.ericabrahamsen.net (Postfix) with ESMTPSA id 9DA68FA089;
 Wed, 30 Oct 2019 23:58:53 +0000 (UTC)
From: Eric Abrahamsen <eric@HIDDEN>
To: bug-gnu-emacs@HIDDEN
Subject: 27.0.50; [PATCH] WIP on using gnus info accessor macros
Date: Wed, 30 Oct 2019 16:58:52 -0700
Message-ID: <875zk5aipv.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]
 [fuzzy]
X-Received-From: 52.70.2.18
X-Spam-Score: -1.4 (-)
X-Debbugs-Envelope-To: submit
Cc: Lars Ingebrigtsen <larsi@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -2.4 (--)

--=-=-=
Content-Type: text/plain


The attached patch is a work-in-progress for making sure that all of
Gnus' code only accesses group infos via the relevant macros --
essentially hiding the fact that group infos are implemented as lists,
in anticipation of eventually being able to re-implement them as structs
at some point in the future.

Essentially, "(nth 3 info)" becomes "(gnus-info-marks info)", and so
one.

It also replaces uses of "gnus-info-set-*" with "(setf (gnus-info-* ".
The setter macros aren't deprecated, though.

My main question is about the use of the EXTEND argument to
`gnus-info-set-marks', `gnus-info-set-method', and
`gnus-info-set-params'. In the current patch, I have left the setter
intact wherever the EXTEND argument is passed, until I can figure this
out.

If I could understand why _some_ of the infos are expected to be short a
few elements (newly-created groups?), I would rather provide a
`make-gnus-info' function (again, in anticipation of a struct
constructor), which could be called with the elements of an info (either
as a list or spread) and return an info filled-out with nils where
necessary. Then that could be used wherever we expect a short info.

There's also the weird spot in gnus-sum.el:6183 where we're chopping off
nil elements from the end of an info list, I don't know why.

One last bit I'm uncertain about is in `nnvirtual-request-update-info',
where I've replaced this:

      (setcar (cddr info) nnvirtual-mapping-reads)
      (if (nthcdr 3 info)
	  (setcar (nthcdr 3 info) nnvirtual-mapping-marks)
	(when nnvirtual-mapping-marks
	  (setcdr (nthcdr 2 info) (list nnvirtual-mapping-marks))))

with this:

      (setf (gnus-info-read info) nnvirtual-mapping-reads)
      (when nnvirtual-mapping-marks
	(setf (gnus-info-marks info) nnvirtual-mapping-marks))

It seems to work fine, but to be honest I don't really understand the
original logic.

Eric


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-WIP-on-using-gnus-info-accessors.patch

From 8e509a640b0496ae419221e45ee36c43bcc8ca94 Mon Sep 17 00:00:00 2001
From: Eric Abrahamsen <eric@HIDDEN>
Date: Wed, 17 Jul 2019 18:49:27 -0700
Subject: [PATCH] WIP on using gnus info accessors

---
 lisp/gnus/gnus-agent.el | 36 +++++++++++-----------
 lisp/gnus/gnus-group.el | 66 ++++++++++++++++++++++-------------------
 lisp/gnus/gnus-int.el   |  2 +-
 lisp/gnus/gnus-sieve.el |  2 +-
 lisp/gnus/gnus-start.el | 64 +++++++++++++++++++--------------------
 lisp/gnus/gnus-sum.el   | 37 ++++++++++++-----------
 lisp/gnus/gnus.el       |  6 ++--
 lisp/gnus/nndiary.el    |  5 ++--
 lisp/gnus/nndraft.el    | 18 +++++------
 lisp/gnus/nnimap.el     | 20 +++++++------
 lisp/gnus/nnir.el       |  8 ++---
 lisp/gnus/nnmaildir.el  |  6 ++--
 lisp/gnus/nnmairix.el   | 38 +++++++++++-------------
 lisp/gnus/nnml.el       |  4 +--
 lisp/gnus/nnvirtual.el  | 17 +++++------
 15 files changed, 168 insertions(+), 161 deletions(-)

diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 1f25255278..a58a35df98 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -1212,22 +1212,21 @@ gnus-agent-synchronize-group-flags
 	      (marks (nth 2 action)))
 	  (dolist (mark marks)
 	    (cond ((eq mark 'read)
-		   (gnus-info-set-read
-		    info
-		    (funcall (if (eq what 'add)
-				 'gnus-range-add
-			       'gnus-remove-from-range)
-			     (gnus-info-read info)
-			     range))
+		   (setf (gnus-info-read info)
+			 (funcall (if (eq what 'add)
+				      'gnus-range-add
+				    'gnus-remove-from-range)
+				  (gnus-info-read info)
+				  range))
 		   (gnus-get-unread-articles-in-group
 		    info
 		    (gnus-active (gnus-info-group info))))
 		  ((memq mark '(tick))
 		   (let ((info-marks (assoc mark (gnus-info-marks info))))
 		     (unless info-marks
-                       (gnus-info-set-marks
-                        info (cons (setq info-marks (list mark))
-                                   (gnus-info-marks info))))
+		       (setf (gnus-info-marks info)
+			     (cons (setq info-marks (list mark))
+				   (gnus-info-marks info))))
                      (setcdr info-marks
                              (funcall (if (eq what 'add)
                                           'gnus-range-add
@@ -1303,12 +1302,11 @@ gnus-agent-possibly-alter-active
           ;; file.
 
           (let ((read (gnus-info-read info)))
-            (gnus-info-set-read
-             info
-             (gnus-range-add
-              read
-              (list (cons (1+ agent-max)
-                          (1- active-min))))))
+	    (setf (gnus-info-read info)
+		  (gnus-range-add
+		   read
+		   (list (cons (1+ agent-max)
+                               (1- active-min))))))
 
           ;; Lie about the agent's local range for this group to
           ;; disable the set read each time this server is opened.
@@ -2535,11 +2533,11 @@ gnus-agent-fetch-group-1
                           (when (cdr marked-arts)
                             (setq marks
 				  (delq marked-arts (gnus-info-marks info)))
-                            (gnus-info-set-marks info marks)))))
+			    (setf (gnus-info-marks info) marks)))))
                     (let ((read (gnus-info-read
 				 (or info (setq info (gnus-get-info group))))))
-                      (gnus-info-set-read
-		       info (gnus-add-to-range read unfetched-articles)))
+		      (setf (gnus-info-read info)
+			    (gnus-add-to-range read unfetched-articles)))
 
                     (gnus-group-update-group group t)
                     (sit-for 0)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 8f5f5d66e4..369c3c2906 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1423,7 +1423,7 @@ gnus-group-update-group-line
 	   (not (gnus-ephemeral-group-p group))
 	   (gnus-dribble-enter
 	    (concat "(gnus-group-set-info '"
-		    (gnus-prin1-to-string (nth 1 entry))
+		    (gnus-prin1-to-string (gnus-get-info group))
 		    ")")
 	    (concat "^(gnus-group-set-info '(\"" (regexp-quote group) "\"")))
       (setq gnus-group-indentation (gnus-group-group-indentation))
@@ -1440,10 +1440,10 @@ gnus-group-insert-group-line-info
     (if entry
 	(progn
 	  ;; (Un)subscribed group.
-	  (setq info (nth 1 entry))
+	  (setq info (gnus-get-info group))
 	  (gnus-group-insert-group-line
 	   group (gnus-info-level info) (gnus-info-marks info)
-	   (or (car entry) t) (gnus-info-method info)))
+	   (or (gnus-group-unread group) t) (gnus-info-method info)))
       ;; This group is dead.
       (gnus-group-insert-group-line
        group
@@ -1457,7 +1457,7 @@ gnus-group-insert-group-line-info
        (gnus-method-simplify (gnus-find-method-for-group group))))))
 
 (defun gnus-number-of-unseen-articles-in-group (group)
-  (let* ((info (nth 1 (gnus-group-entry group)))
+  (let* ((info (gnus-get-info group))
 	 (marked (gnus-info-marks info))
 	 (seen (cdr (assq 'seen marked)))
 	 (active (gnus-active group)))
@@ -1595,15 +1595,15 @@ gnus-group-update-eval-form
   "Eval `car' of each element of LIST, and return the first that return t.
 Some value are bound so the form can use them."
   (when list
-    (let* ((entry (gnus-group-entry group))
+    (let* ((unread (gnus-group-unread group))
            (active (gnus-active group))
-           (info (nth 1 entry))
+           (info (gnus-get-info group))
            (method (inline (gnus-server-get-method
 			    group (gnus-info-method info))))
            (marked (gnus-info-marks info))
 	   (env
 	    (list
-	     (cons 'unread (if (numberp (car entry)) (car entry) 0))
+	     (cons 'unread (if (numberp unread) unread 0))
 	     (cons 'total (if active (1+ (- (cdr active) (car active))) 0))
 	     (cons 'mailp (apply
 			   'append
@@ -1676,7 +1676,7 @@ gnus-group-update-group
 			 (not (gnus-ephemeral-group-p group)))
 		(gnus-dribble-enter
 		 (concat "(gnus-group-set-info '"
-			 (gnus-prin1-to-string (nth 1 entry))
+			 (gnus-prin1-to-string (gnus-get-info group))
 			 ")")
 		 (concat "^(gnus-group-set-info '(\""
 			 (regexp-quote group) "\"")))))
@@ -2958,9 +2958,9 @@ gnus-group-edit-group-done
 			(if (or (not method)
 				(gnus-server-equal
 				 gnus-select-method method))
-			    (gnus-group-real-name (car info))
+			    (gnus-group-real-name group)
 			  (gnus-group-prefixed-name
-			   (gnus-group-real-name (car info)) method))
+			   (gnus-group-real-name group) method))
 		      nil)))
     (when (and new-group
 	       (not (equal new-group group)))
@@ -2973,11 +2973,11 @@ gnus-group-edit-group-done
       (setq info (copy-tree info))
       (setcar info new-group)
       (unless (gnus-server-equal method "native")
-	(unless (nthcdr 3 info)
+	(unless (gnus-info-marks info)
 	  (nconc info (list nil nil)))
-	(unless (nthcdr 4 info)
+	(unless (gnus-info-method info)
 	  (nconc info (list nil)))
-	(gnus-info-set-method info method))
+	(setf (gnus-info-method info) method))
       (gnus-group-set-info info))
     (gnus-group-update-group (or new-group group))
     (gnus-group-position-point)))
@@ -3531,17 +3531,18 @@ gnus-info-clear-data
     (gnus-undo-register
       `(progn
 	 (gnus-request-set-mark ,group ',action)
+	 ;; FIXME: Handle EXTEND.
 	 (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-	 (gnus-info-set-read ',info ',(gnus-info-read info))
+	 (setf (gnus-info-read ',info) ',(gnus-info-read info))
 	 (when (gnus-group-jump-to-group ,group)
 	   (gnus-get-unread-articles-in-group ',info ',(gnus-active group) t)
 	   (gnus-group-update-group-line))))
     (setq action (mapcar (lambda (el) (list (nth 0 el) 'del (nth 2 el)))
 			 action))
     (gnus-request-set-mark group action)
-    (gnus-info-set-read info nil)
+    (setf (gnus-info-read info) nil)
     (when (gnus-info-marks info)
-      (gnus-info-set-marks info nil))))
+      (setf (gnus-info-marks info) nil))))
 
 ;; Group catching up.
 
@@ -3903,7 +3904,7 @@ gnus-group-yank-group
     (while (>= (cl-decf arg) 0)
       (when (not (setq info (pop gnus-list-of-killed-groups)))
 	(error "No more newsgroups to yank"))
-      (push (setq group (nth 1 info)) out)
+      (push (setq group (gnus-info-group info)) out)
       ;; Find which newsgroup to insert this one before - search
       ;; backward until something suitable is found.  If there are no
       ;; other newsgroups in this buffer, just make this newsgroup the
@@ -4413,6 +4414,7 @@ gnus-group-browse-foreign-server
   (gnus-browse-foreign-server method))
 
 (defun gnus-group-set-info (info &optional method-only-group part)
+  "Update status for group represented by INFO."
   (when (or info part)
     (let* ((entry (gnus-group-entry
 		   (or method-only-group (gnus-info-group info))))
@@ -4459,11 +4461,12 @@ gnus-group-set-info
       ;; can do the update.
       (if entry
 	  (progn
-	    (setcar (nthcdr 1 entry) info)
+	    (gnus-set-info (nthcdr 1 entry) info)
 	    (when (and (not (eq (car entry) t))
 		       (gnus-active (gnus-info-group info)))
-	      (setcar entry (length
-			     (gnus-list-of-unread-articles (car info)))))
+	      (setf (gnus-group-unread (gnus-info-group info))
+		    (length
+		     (gnus-list-of-unread-articles (car info)))))
 	    ;; The above `setcar' will only affect the hashtable, not
 	    ;; the alist: update the alist separately, but only if
 	    ;; it's been initialized.
@@ -4497,20 +4500,23 @@ gnus-add-marked-articles
   (let ((info (or info (gnus-get-info group)))
 	marked m)
     (or (not info)
-	(and (not (setq marked (nthcdr 3 info)))
+	(and (not (setq marked (gnus-info-marks info)))
 	     (or (null articles)
-		 (setcdr (nthcdr 2 info)
-			 (list (list (cons type (gnus-compress-sequence
-						 articles t)))))))
-	(and (not (setq m (assq type (car marked))))
+		 ;; Group had no marks at all, set unconditionally.
+		 (setf (gnus-info-marks info)
+		       (list (cons type (gnus-compress-sequence
+					 articles t))))))
+	(and (not (setq m (assq type marked)))
 	     (or (null articles)
-		 (setcar marked
-			 (cons (cons type (gnus-compress-sequence articles t) )
-			       (car marked)))))
+		 ;; Group had no marks of TYPE.
+		 (setf (gnus-info-marks info)
+		       (cons (cons type (gnus-compress-sequence articles t))
+			     marked))))
 	(if force
+	    ;; Replace (or remove) all marks of TYPE.
 	    (if (null articles)
-		(setcar (nthcdr 3 info)
-			(assq-delete-all type (car marked)))
+		(setf (gnus-info-marks info)
+		      (assq-delete-all type marked))
 	      (setcdr m (gnus-compress-sequence articles t)))
 	  (setcdr m (gnus-compress-sequence
 		     (sort (nconc (gnus-uncompress-range (cdr m))
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 0abbfe6720..a21bc25840 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -727,7 +727,7 @@ gnus-request-marks
 	       (let* ((range (if (= min 2) 1 (cons 1 (1- min))))
 		      (read (gnus-info-read info))
 		      (new-read (gnus-range-add read (list range))))
-		 (gnus-info-set-read info new-read)))
+		 (setf (gnus-info-read info) new-read)))
 	     info)))))
 
 (defun gnus-request-expire-articles (articles group &optional force)
diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el
index fc0bf3098b..5edd6f5f7a 100644
--- a/lisp/gnus/gnus-sieve.el
+++ b/lisp/gnus/gnus-sieve.el
@@ -128,7 +128,7 @@ gnus-sieve-article-add-rule
 	  (info (gnus-get-info gnus-newsgroup-name)))
       (if (null rule)
 	  (error "Could not guess rule for article")
-	(gnus-info-set-params info (cons rule (gnus-info-params info)))
+	(push rule (gnus-info-params info))
 	(message "Added rule in group %s for article: %s" gnus-newsgroup-name
 		 rule)))))
 
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index e142c438ee..b8126433a4 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1295,7 +1295,7 @@ gnus-group-change-level
        (t
 	(when (and (>= level gnus-level-zombie)
 		   entry)
-	  (remhash (car (nth 1 entry)) gnus-newsrc-hashtb)
+	  (remhash group gnus-newsrc-hashtb)
 	  (setq gnus-group-list (remove group gnus-group-list))
 	  (setq gnus-newsrc-alist (delq (assoc group gnus-newsrc-alist)
 					gnus-newsrc-alist)))))
@@ -1323,7 +1323,7 @@ gnus-group-change-level
 	    ;; It was alive, and it is going to stay alive, so we
 	    ;; just change the level and don't change any pointers or
 	    ;; hash table entries.
-	    (setcar (cdadr entry) level)
+	    (setf (gnus-info-level (nth 1 entry)) level)
 	  (if (listp entry)
 	      (setq info (cdr entry)
 		    num (car entry))
@@ -1577,7 +1577,7 @@ gnus-get-unread-articles-in-group
       ;; Set the number of unread articles.
       (when (and info
 		 (gnus-group-entry (gnus-info-group info)))
-	(setcar (gnus-group-entry (gnus-info-group info)) num))
+	(setf (gnus-group-unread (gnus-info-group info)) num))
       num)))
 
 ;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
@@ -1603,7 +1603,7 @@ gnus-get-unread-articles
 	 (gnus-agent-article-local-times 0)
 	 (archive-method (gnus-server-to-method "archive"))
 	 infos info group active method cmethod
-	 method-type method-group-list entry)
+	 method-type method-group-list)
     (gnus-message 6 "Checking new news...")
 
     (while newsrc
@@ -1650,8 +1650,8 @@ gnus-get-unread-articles
 	;; It leads `(gnus-group-unread group)' to return t.  See also
 	;; `gnus-group-prepare-flat'.
 	(unless active
-	  (when (setq entry (gnus-group-entry group))
-	    (setcar entry t)))))
+	  (when (gnus-group-entry group)
+	    (setf (gnus-group-unread group) t)))))
 
     ;; Sort the methods based so that the primary and secondary
     ;; methods come first.  This is done for legacy reasons to try to
@@ -1828,7 +1828,7 @@ gnus-make-hashtable-from-newsrc-alist
       ;; Make the same select-methods identical Lisp objects.
       (when (setq method (gnus-info-method info))
 	(if (setq rest (member method methods))
-	    (gnus-info-set-method info (car rest))
+	    (setf (gnus-info-method info) (car rest))
 	  (push method methods)))
       ;; Check for encoded group names and decode them.
       (when (string-match-p "[^[:ascii:]]" (setq gname (car info)))
@@ -1879,9 +1879,9 @@ gnus-parse-active
 
 (defun gnus-make-articles-unread (group articles)
   "Mark ARTICLES in GROUP as unread."
-  (let* ((info (nth 1 (or (gnus-group-entry group)
-			  (gnus-group-entry
-			   (gnus-group-real-name group)))))
+  (let* ((info (or (gnus-get-info group)
+		   (gnus-get-info
+		    (gnus-group-real-name group))))
 	 (ranges (gnus-info-read info))
 	 news article)
     (while articles
@@ -1890,8 +1890,8 @@ gnus-make-articles-unread
 	(push article news)))
     (when news
       ;; Enter this list into the group info.
-      (gnus-info-set-read
-       info (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
+      (setf (gnus-info-read info)
+	    (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
 
       ;; Set the number of unread articles in gnus-newsrc-hashtb.
       (gnus-get-unread-articles-in-group info (gnus-active group))
@@ -1901,9 +1901,8 @@ gnus-make-articles-unread
 
 (defun gnus-make-ascending-articles-unread (group articles)
   "Mark ascending ARTICLES in GROUP as unread."
-  (let* ((entry (or (gnus-group-entry group)
-                    (gnus-group-entry (gnus-group-real-name group))))
-         (info (nth 1 entry))
+  (let* ((info (or (gnus-get-info group)
+                   (gnus-get-info (gnus-group-real-name group))))
 	 (ranges (gnus-info-read info))
          (r ranges)
 	 modified)
@@ -1911,7 +1910,7 @@ gnus-make-ascending-articles-unread
     (while articles
       (let ((article (pop articles))) ; get the next article to remove from ranges
         (while (let ((range (car ranges))) ; note the current range
-                 (if (atom range)       ; single value range
+                 (if (atom range)	   ; single value range
                      (cond ((not range)
                             ;; the articles extend past the end of the ranges
                             ;; OK - I'm done
@@ -1958,7 +1957,7 @@ gnus-make-ascending-articles-unread
       (when (eq modified 'remove-null)
         (setq r (delq nil r)))
       ;; Enter this list into the group info.
-      (gnus-info-set-read info r)
+      (setf (gnus-info-read info) r)
 
       ;; Set the number of unread articles in gnus-newsrc-hashtb.
       (gnus-get-unread-articles-in-group info (gnus-active group))
@@ -2362,12 +2361,11 @@ gnus-convert-old-ticks
 	(setq dormant (cdr (assq 'dormant marks))
 	      ticked (cdr (assq 'tick marks)))
 	(when (or dormant ticked)
-	  (gnus-info-set-read
-	   info
-	   (gnus-add-to-range
-	    (gnus-info-read info)
-	    (nconc (gnus-uncompress-range dormant)
-		   (gnus-uncompress-range ticked)))))))))
+	  (setf (gnus-info-read info)
+		(gnus-add-to-range
+		 (gnus-info-read info)
+		 (nconc (gnus-uncompress-range dormant)
+			(gnus-uncompress-range ticked)))))))))
 
 (defun gnus-load (file)
   "Load FILE, but in such a way that read errors can be reported."
@@ -2438,9 +2436,9 @@ gnus-read-old-newsrc-el-file
       (while (setq group (pop newsrc))
 	(if (setq info (gnus-get-info (car group)))
 	    (progn
-	      (gnus-info-set-read info (cddr group))
-	      (gnus-info-set-level
-	       info (if (nth 1 group) gnus-level-default-subscribed
+	      (setf (gnus-info-read info) (cddr group))
+	      (setf (gnus-info-level info)
+		    (if (nth 1 group) gnus-level-default-subscribed
 		      gnus-level-default-unsubscribed))
 	      (push info gnus-newsrc-alist))
 	  (push (setq info
@@ -2451,10 +2449,10 @@ gnus-read-old-newsrc-el-file
 		gnus-newsrc-alist))
 	;; Copy marks into info.
 	(when (setq m (assoc (car group) marked))
-	  (unless (nthcdr 3 info)
+	  (unless (gnus-info-marks info)
 	    (nconc info (list nil)))
-	  (gnus-info-set-marks
-	   info (list (cons 'tick (gnus-compress-sequence
+	  (setf (gnus-info-marks info)
+		(list (cons 'tick (gnus-compress-sequence
 				   (sort (cdr m) '<) t))))))
       (setq newsrc killed)
       (while newsrc
@@ -2609,7 +2607,7 @@ gnus-newsrc-to-gnus-format
 		;; There is an entry for this file in
 		;; `gnus-newsrc-hashtb'.
 		(progn
-		  (gnus-info-set-read info (nreverse reads))
+		  (setf (gnus-info-read info) (nreverse reads))
 		  ;; We update the level very gently.  In fact, we
 		  ;; only change it if there's been a status change
 		  ;; from subscribed to unsubscribed, or vice versa.
@@ -2621,7 +2619,7 @@ gnus-newsrc-to-gnus-format
 				       (1+ gnus-level-default-unsubscribed))))
 			((and (> level gnus-level-subscribed) subscribed)
 			 (setq level gnus-level-default-subscribed)))
-		  (gnus-info-set-level info level))
+		  (setf (gnus-info-level info) level))
 	      ;; This is a new group.
 	      (setq info (list group
 			       (if subscribed
@@ -2645,7 +2643,7 @@ gnus-newsrc-to-gnus-format
 	    (prev gnus-newsrc-alist)
 	    entry mentry)
 	(while rc
-	  (or (null (nth 4 (car rc)))	; It's a native group.
+	  (or (null (gnus-info-method (car rc))) ; It's a native group.
 	      (assoc (caar rc) newsrc)	; It's already in the alist.
 	      (if (setq entry (assoc (caar prev) newsrc))
 		  (setcdr (setq mentry (memq entry newsrc))
@@ -2952,7 +2950,7 @@ gnus-gnus-to-newsrc-format
 	(insert gnus-newsrc-options))
       ;; Write subscribed and unsubscribed.
       (dolist (g-name groups)
-	(setq info (nth 1 (gnus-group-entry g-name)))
+	(setq info (gnus-get-info g-name))
 	;; Maybe don't write foreign groups to .newsrc.
 	(when (or (null (setq method (gnus-info-method info)))
 		  (equal method "native")
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index f21bc7584e..b235df8439 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -6178,6 +6178,7 @@ gnus-update-marks
 	(when newmarked
 	  (setcdr (nthcdr 2 info) (list newmarked))))
 
+      ;; FIXME: Why is this necessary?
       ;; Cut off the end of the info if there's nothing else there.
       (let ((i 5))
 	(while (and (> i 2)
@@ -6278,7 +6279,7 @@ gnus-create-xref-hashtb
 (defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads)
   "Look through all the headers and mark the Xrefs as read."
   (let ((virtual (gnus-virtual-group-p from-newsgroup))
-	info xref-hashtb method nth4)
+	info xref-hashtb method tmp-method)
     (with-current-buffer gnus-group-buffer
       (when (setq xref-hashtb
 		  (gnus-create-xref-hashtb from-newsgroup headers unreads))
@@ -6288,17 +6289,18 @@ gnus-mark-xrefs-as-read
 	     ;; Dead groups are not updated.
 	     (and (prog1
 		      (setq info (gnus-get-info group))
-		    (when (stringp (setq nth4 (gnus-info-method info)))
-		      (setq nth4 (gnus-server-to-method nth4))))
+		    (when (stringp (setq tmp-method (gnus-info-method info)))
+		      (setq tmp-method (gnus-server-to-method tmp-method))))
 		  ;; Only do the xrefs if the group has the same
 		  ;; select method as the group we have just read.
 		  (or (gnus-methods-equal-p
-		       nth4 (gnus-find-method-for-group from-newsgroup))
+		       tmp-method (gnus-find-method-for-group from-newsgroup))
 		      virtual
-		      (equal nth4 (setq method (gnus-find-method-for-group
-						from-newsgroup)))
-		      (and (equal (car nth4) (car method))
-			   (equal (nth 1 nth4) (nth 1 method))))
+		      (equal tmp-method
+			     (setq method (gnus-find-method-for-group
+					   from-newsgroup)))
+		      (and (equal (car tmp-method) (car method))
+			   (equal (nth 1 tmp-method) (nth 1 method))))
 		  gnus-use-cross-reference
 		  (or (not (eq gnus-use-cross-reference t))
 		      virtual
@@ -6310,7 +6312,7 @@ gnus-mark-xrefs-as-read
 
 (defun gnus-compute-read-articles (group articles)
   (let* ((entry (gnus-group-entry group))
-	 (info (nth 1 entry))
+	 (info (gnus-get-info entry))
 	 (active (gnus-active group))
 	 ninfo)
     (when entry
@@ -6347,7 +6349,7 @@ gnus-group-make-articles-read
   "Update the info of GROUP to say that ARTICLES are read."
   (let* ((num 0)
 	 (entry (gnus-group-entry group))
-	 (info (nth 1 entry))
+	 (info (gnus-get-info entry))
 	 (active (gnus-active group))
 	 (set-marks
 	  (gnus-method-option-p
@@ -6367,7 +6369,7 @@ gnus-group-make-articles-read
 	(gnus-undo-register
 	  `(progn
 	     (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-	     (gnus-info-set-read ',info ',(gnus-info-read info))
+	     (setf (gnus-info-read ',info) ',(gnus-info-read info))
 	     (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
 	     (when ,set-marks
 	       (gnus-request-set-mark
@@ -6375,7 +6377,7 @@ gnus-group-make-articles-read
 	     (gnus-group-jump-to-group ,group)
 	     (gnus-group-update-group ,group t))))
       ;; Add the read articles to the range.
-      (gnus-info-set-read info range)
+      (setf (gnus-info-read info) range)
       (when set-marks
 	(gnus-request-set-mark group (list (list range 'add '(read)))))
       ;; Then we have to re-compute how many unread
@@ -6395,7 +6397,7 @@ gnus-group-make-articles-read
 	    (setq range (cdr range)))
 	  (setq num (- (cdr active) num))))
 	;; Update the number of unread articles.
-	(setcar entry num)
+	(setf (gnus-group-unread group) num)
 	;; Update the group buffer.
 	(unless (gnus-ephemeral-group-p group)
 	  (gnus-group-update-group group t))))))
@@ -10283,8 +10285,8 @@ gnus-summary-move-article
 	    (when (and (not (memq article gnus-newsgroup-unreads))
 		       (cdr art-group))
 	      (push 'read to-marks)
-	      (gnus-info-set-read
-	       info (gnus-add-to-range (gnus-info-read info)
+	      (setf (gnus-info-read info)
+		    (gnus-add-to-range (gnus-info-read info)
 				       (list (cdr art-group)))))
 
 	    ;; See whether the article is to be put in the cache.
@@ -12894,15 +12896,16 @@ gnus-update-read-articles
 	    (set-buffer gnus-group-buffer)
 	    (gnus-undo-register
 	      `(progn
+		 ;;FIXME: A better way of ensuring info completness?
 		 (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-		 (gnus-info-set-read ',info ',(gnus-info-read info))
+		 (setf (gnus-info-read ',info) ',(gnus-info-read info))
 		 (gnus-group-jump-to-group ,group)
 		 (gnus-get-unread-articles-in-group ',info
 						    (gnus-active ,group))
 		 (gnus-group-update-group ,group t)
 		 ,setmarkundo))))
 	;; Enter this list into the group info.
-	(gnus-info-set-read info read)
+	(setf (gnus-info-read info) read)
 	;; Set the number of unread articles in gnus-newsrc-hashtb.
 	(gnus-get-unread-articles-in-group info (gnus-active group))
 	t))))
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 0673ac15f6..dd0c83ad94 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -3689,6 +3689,7 @@ gnus-group-set-parameter
 	    (setq new-params (append new-params (list (car old-params)))))
 	  (setq old-params (cdr old-params)))
 	(if (listp group)
+	    ;; FIXME: Address EXTEND.
 	    (gnus-info-set-params info new-params t)
 	  (gnus-group-set-info new-params (gnus-info-group info) 'params))))))
 
@@ -3704,14 +3705,15 @@ gnus-group-remove-parameter
 	  (setq params (delq name params))
 	  (while (assq name params)
 	    (gnus-alist-pull name params))
-	  (gnus-info-set-params info params))))))
+	  (setf (gnus-info-params info) params))))))
 
 (defun gnus-group-add-score (group &optional score)
   "Add SCORE to the GROUP score.
 If SCORE is nil, add 1 to the score of GROUP."
   (let ((info (gnus-get-info group)))
     (when info
-      (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
+      (setf (gnus-info-score info)
+	    (+ (gnus-info-score info) (or score 1))))))
 
 (defun gnus-short-group-name (group &optional levels)
   "Collapse GROUP name LEVELS.
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index f79d8f1707..88bb5651e2 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -795,8 +795,9 @@ nndiary-request-update-info
 	  (kill-buffer buf))
 	(setq unread (sort unread '<))
 	(and unread
-	     (gnus-info-set-read info (gnus-update-read-articles
-				       (gnus-info-group info) unread t)))
+	     (setf (gnus-info-read info)
+		   (gnus-update-read-articles
+		    (gnus-info-group info) unread t)))
 	))
     (run-hook-with-args 'nndiary-request-update-info-functions
 			(gnus-info-group info))
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index bc475ee295..cc9923164a 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -147,17 +147,17 @@ nndraft-request-restore-buffer
 
 (deffoo nndraft-request-update-info (group info &optional server)
   (nndraft-possibly-change-group group)
-  (gnus-info-set-read
-   info
-   (gnus-update-read-articles (gnus-group-prefixed-name group '(nndraft ""))
-			      (nndraft-articles) t))
-  (let ((marks (nth 3 info)))
+  (setf (gnus-info-read info)
+	(gnus-update-read-articles
+	 (gnus-group-prefixed-name group '(nndraft ""))
+	 (nndraft-articles) t))
+  (let ((marks (gnus-info-marks info)))
     (when marks
       ;; Nix out all marks except the `unsend'-able article marks.
-      (setcar (nthcdr 3 info)
-	      (if (assq 'unsend marks)
-		  (list (assq 'unsend marks))
-		nil))))
+      (setf (gnus-info-marks info)
+	    (if (assq 'unsend marks)
+		(list (assq 'unsend marks))
+	      nil))))
   t)
 
 (defun nndraft-generate-headers ()
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 856ac75cd6..365f8e49d0 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1620,7 +1620,7 @@ nnimap-update-info
 		       read)))
 	      (when (or (not (listp permanent-flags))
 			(memq '%Seen permanent-flags))
-		(gnus-info-set-read info read))
+		(setf (gnus-info-read info) read))
 	      ;; Update the marks.
 	      (setq marks (gnus-info-marks info))
 	      (dolist (type (cdr nnimap-mark-alist))
@@ -1663,6 +1663,7 @@ nnimap-update-info
 		(if old-unexists
 		    (setcdr old-unexists unexists)
 		  (push (cons 'unexist unexists) marks)))
+	      ;; FIXME: Handle EXTEND.
 	      (gnus-info-set-marks info marks t))))
 	;; Tell Gnus whether there are any \Recent messages in any of
 	;; the groups.
@@ -1680,14 +1681,13 @@ nnimap-update-info
 
 (defun nnimap-update-qresync-info (info existing vanished flags)
   ;; Add all the vanished articles to the list of read articles.
-  (gnus-info-set-read
-   info
-   (gnus-add-to-range
-    (gnus-add-to-range
-     (gnus-range-add (gnus-info-read info)
-		     vanished)
-     (cdr (assq '%Flagged flags)))
-    (cdr (assq '%Seen flags))))
+  (setf (gnus-info-read info)
+	(gnus-add-to-range
+	 (gnus-add-to-range
+	  (gnus-range-add (gnus-info-read info)
+			  vanished)
+	  (cdr (assq '%Flagged flags)))
+	 (cdr (assq '%Seen flags))))
   (let ((marks (gnus-info-marks info)))
     (dolist (type (cdr nnimap-mark-alist))
       (let ((ticks (assoc (car type) marks))
@@ -1707,6 +1707,7 @@ nnimap-update-qresync-info
 			(gnus-sorted-complement existing new-marks))))
 	  (when ticks
 	    (push (cons (car type) ticks) marks))
+	  ;; FIXME: Handle EXTEND.
 	  (gnus-info-set-marks info marks t))))
     ;; Add vanished to the list of unexisting articles.
     (when vanished
@@ -1715,6 +1716,7 @@ nnimap-update-qresync-info
 	(if old-unexists
 	    (setcdr old-unexists unexists)
 	  (push (cons 'unexist unexists) marks)))
+      ;; FIXME: Handle EXTEND.
       (gnus-info-set-marks info marks t))))
 
 (defun nnimap-imap-ranges-to-gnus-ranges (irange)
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 7cb2d1615a..45fbadf23c 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -874,8 +874,8 @@ nnir-request-set-mark
 (deffoo nnir-request-update-info (group info &optional server)
   (nnir-possibly-change-group group server)
   ;; clear out all existing marks.
-  (gnus-info-set-marks info nil)
-  (gnus-info-set-read info nil)
+  (setf (gnus-info-marks info) nil)
+  (setf (gnus-info-read info) nil)
   (let ((group (gnus-group-guess-full-name-from-command-method group))
 	(articles-by-group
 	 (nnir-categorize
@@ -889,8 +889,8 @@ nnir-request-update-info
 	     (group-info (gnus-get-info (car group-articles)))
 	     (marks (gnus-info-marks group-info))
 	     (read (gnus-info-read group-info)))
-	(gnus-info-set-read
-	 info
+	(setf
+	 (gnus-info-read info)
 	 (gnus-add-to-range
 	  (gnus-info-read info)
 	  (delq nil
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 0133fc6ce2..2fc773f74f 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -1000,7 +1000,8 @@ nnmaildir-request-update-info
 	    pgname (nnmaildir--pgname nnmaildir--cur-server gname)
 	    flist (nnmaildir--grp-flist group))
       (when (zerop (nnmaildir--grp-count group))
-	(gnus-info-set-read info nil)
+	(setf (gnus-info-read info) nil)
+	;; FIXME: Handle EXTEND.
 	(gnus-info-set-marks info nil 'extend)
 	(throw 'return info))
       (setq old-marks (cons 'read (gnus-info-read info))
@@ -1083,7 +1084,8 @@ nnmaildir-request-update-info
 	    (setq ranges (gnus-add-to-range ranges (sort article-list '<)))))
 	(if (eq mark 'read) (setq read ranges)
 	  (if ranges (setq marks (cons (cons mark ranges) marks)))))
-      (gnus-info-set-read info (gnus-range-add read missing))
+      (setf (gnus-info-read info) (gnus-range-add read missing))
+      ;; FIXME: Handle EXTEND.
       (gnus-info-set-marks info marks 'extend)
       (setf (nnmaildir--grp-mmth group) new-mmth)
       info)))
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index 6c5502ac3d..722cb95306 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -711,29 +711,27 @@ nnmairix-request-marks
 	    (nnimap-request-update-info-internal folder folderinfo nnmairix-backend-server)
 	  (nnmairix-call-backend "request-update-info" folder folderinfo nnmairix-backend-server))
 	;; set range of read articles
-	(gnus-info-set-read
-	 info
-	 (if docorr
-	     (nnmairix-map-range
-	      `(lambda (x) (+ x ,(cadr corr)))
-	      (gnus-info-read folderinfo))
-	   (gnus-info-read folderinfo)))
+	(setf (gnus-info-read info)
+	      (if docorr
+		  (nnmairix-map-range
+		   `(lambda (x) (+ x ,(cadr corr)))
+		   (gnus-info-read folderinfo))
+		(gnus-info-read folderinfo)))
 	;; set other marks
-	(gnus-info-set-marks
-	 info
-	 (if docorr
-	     (mapcar (lambda (cur)
-			 (cons
-			  (car cur)
-			  (nnmairix-map-range
-			   `(lambda (x) (+ x ,(cadr corr)))
-			   (list (cadr cur)))))
-		     (gnus-info-marks folderinfo))
-	   (gnus-info-marks folderinfo))))
+	(setf (gnus-info-marks info)
+	      (if docorr
+		  (mapcar (lambda (cur)
+			    (cons
+			     (car cur)
+			     (nnmairix-map-range
+			      `(lambda (x) (+ x ,(cadr corr)))
+			      (list (cadr cur)))))
+			  (gnus-info-marks folderinfo))
+		(gnus-info-marks folderinfo))))
       (when (eq readmarks 'unread)
-	(gnus-info-set-read info nil))
+	(setf (gnus-info-read info) nil))
       (when (eq readmarks 'read)
-	(gnus-info-set-read info (gnus-active qualgroup))))
+	(setf (gnus-info-read info) (gnus-active qualgroup))))
   t)
 
 (nnoo-define-skeleton nnmairix)
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 302589bd6d..8d8d5ae83a 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1067,7 +1067,7 @@ nnml-request-compact-group
 		  (when (gnus-member-of-range old-number read)
 		    (setq read (gnus-remove-from-range read (list old-number)))
 		    (setq read (gnus-add-to-range read (list new-number))))
-		  (gnus-info-set-read info read))
+		  (setf (gnus-info-read info) read))
 		;; 2 b/ marked articles:
 		(let ((oldmarks (gnus-info-marks info))
 		      mark newmarks)
@@ -1080,7 +1080,7 @@ nnml-request-compact-group
 		      (setcdr mark (gnus-add-to-range (cdr mark)
 						      (list new-number))))
 		    (push mark newmarks))
-		  (gnus-info-set-marks info newmarks))
+		  (setf (gnus-info-marks info) newmarks))
 		;; 3/ Update the NOV entry for this article:
 		(unless nnml-nov-is-evil
 		  (with-current-buffer (nnml-open-nov group)
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index 25f3413fcd..0a4d33cfab 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -307,11 +307,9 @@ nnvirtual-request-update-info
     ;; Install the precomputed lists atomically, so the virtual group
     ;; is not left in a half-way state in case of C-g.
     (gnus-atomic-progn
-      (setcar (cddr info) nnvirtual-mapping-reads)
-      (if (nthcdr 3 info)
-	  (setcar (nthcdr 3 info) nnvirtual-mapping-marks)
-	(when nnvirtual-mapping-marks
-	  (setcdr (nthcdr 2 info) (list nnvirtual-mapping-marks))))
+      (setf (gnus-info-read info) nnvirtual-mapping-reads)
+      (when nnvirtual-mapping-marks
+	(setf (gnus-info-marks info) nnvirtual-mapping-marks))
       (setq nnvirtual-info-installed t))
     t))
 
@@ -463,11 +461,10 @@ nnvirtual-update-read-and-marked
 	(dolist (group nnvirtual-component-groups)
 	  (when (and (setq info (gnus-get-info group))
 		     (gnus-info-marks info))
-	    (gnus-info-set-marks
-	     info
-	     (if (assq 'score (gnus-info-marks info))
-		 (list (assq 'score (gnus-info-marks info)))
-	       nil))))
+	    (setf (gnus-info-marks info)
+		  (if (assq 'score (gnus-info-marks info))
+		      (list (assq 'score (gnus-info-marks info)))
+		    nil))))
 
 	;; Ok, currently type-marks is an assq list with keys of a mark type,
 	;; with data of an assq list with keys of component group names
-- 
2.23.0


--=-=-=--




Acknowledgement sent to Eric Abrahamsen <eric@HIDDEN>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs@HIDDEN. Full text available.
Report forwarded to bug-gnu-emacs@HIDDEN:
bug#38000; Package emacs. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Sat, 2 Nov 2019 14:45:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.