Subject: bug#73041: 30.0.90; track-changes-mode logs warnings (#70541 regression? not actually fixed?)

From: Stefan Monnier <[email-masked]>
Date: Thu, 17 Oct 2024 11:45:24 -0400

>  1. cargo new --vcs git foo
>  2. echo 'mod foo;' >> foo/src/main.rs
>  3. emacs -Q foo/src/foo.rs
>     (foo.rs DOES NOT EXIST YET -- that is part of the bug)
>  4. M-x rust-ts-mode RET
>  5. (progn (setq track-changes-record-errors 'trace) (setq debug-on-error t))
>  6. C-x C-f main.rs RET
>  7. M-x eglot RET
>  8. echo 'struct foo;' > foo/src/foo.rs
>  9. C-x C-f foo.rs RET
> 10. yes RET

Thanks, I managed to reproduce it locally with:

    rm foo.c
    emacs -Q foo.c -f eglot
    echo 'struct foo;' > foo.c
    M-x revert-buffer RET

and that pointed to a bug in `track-changes.el` which could explain the
problem you reported originally.

So, I pushed the patch below to `emacs-30`.

It seems part of the problem also comes from `insert-file-contents`
which apparently fails to run the `before-change-functions` in the above
recipe, but I haven't investigated this any further yet, and
track-changes *should* tolerate this (potentially emitting a warning
along the way), and with the patch, the above recipe now works for me
without error nor warning.

        Stefan

diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el
index 92d14959763..1d5c5e9917a 100644
--- a/lisp/emacs-lisp/track-changes.el
+++ b/lisp/emacs-lisp/track-changes.el
@@ -555,16 +555,16 @@ track-changes--before
 
 (defun track-changes--after (beg end len)
   (cl-assert track-changes--state)
-  (and (eq track-changes--before-clean 'unset)
-       (not track-changes--before-no)
-       ;; This can be a sign that a `before-change-functions' went missing,
-       ;; or that we called `track-changes--clean-state' between
-       ;; a `before-change-functions' and `after-change-functions'.
-       (track-changes--before beg end))
-  (setq track-changes--before-clean nil)
   (let ((offset (- (- end beg) len)))
-    (cl-incf track-changes--before-end offset)
     (cl-incf track-changes--buffer-size offset)
+    (if (and (eq track-changes--before-clean 'unset)
+             (not track-changes--before-no))
+         ;; This can be a sign that a `before-change-functions' went missing,
+         ;; or that we called `track-changes--clean-state' between
+         ;; a `before-change-functions' and `after-change-functions'.
+         (track-changes--before beg end)
+      (cl-incf track-changes--before-end offset))
+    (setq track-changes--before-clean nil)
     (if (not (or track-changes--before-no
                  (save-restriction
                    (widen)