Subject: bug#77612: [PATCH] (eieio-backward-compatibility): Change default to new `warn` value

From: Stefan Monnier <[email-masked]>
Date: Mon, 07 Apr 2025 13:29:35 -0400

Tags: patch

See commit message below.  I also encourage everyone to set
`eieio-backward-compatibility` to nil in their `.emacs`.

        Stefan

 In GNU Emacs 31.0.50 (build 2, i686-pc-linux-gnu, GTK+ Version 3.24.48,
 cairo version 1.18.2) of 2025-03-15 built on alfajor
Repository revision: 4a378e3b325ff3cb84307a2ff4d05ab9ffe24905
Repository branch: work
Windowing system distributor 'The X.Org Foundation', version 11.0.12101015
System Description: Debian GNU/Linux trixie/sid

Configured using:
 'configure -C --enable-checking --enable-check-lisp-object-type --with-modules --with-cairo --with-tiff=ifavailable
 'CFLAGS=-Wall -g3 -Og -Wno-pointer-sign'
 PKG_CONFIG_PATH=/home/monnier/lib/pkgconfig'

>From 5864b71a28be9fcf89fe0ba3603901f33f3fde78 Mon Sep 17 00:00:00 2001
From: Stefan Monnier <[email-masked]>
Date: Mon, 7 Apr 2025 13:27:26 -0400
Subject: [PATCH] (eieio-backward-compatibility): Change default to new `warn`
 value

`eieio-backward-compatibility` controls compatibility with
features declared obsolete since Emacs-25.  I'm not sure
we're ready to remove support for those features (i.e. to set
`eieio-backward-compatibility` to nil), so instead I suggest
to make uses of those features emit warnings not only at
compile-time but also at run-time.

* lisp/emacs-lisp/eieio-core.el (eieio-backward-compatibility):
Change default to new value `warn`.
(eieio-defclass-internal): Obey the new `warn` value of
`eieio-backward-compatibility` in `<CLASS>-list-p` predicates.

* lisp/emacs-lisp/eieio-base.el (make-instance): Remove backward
compatibility when `eieio-backward-compatibility` is nil and emit
a warning if `eieio-backward-compatibility` is `warn`.
(eieio-persistent-make-instance):
Obey the new `warn` value of `eieio-backward-compatibility`.

* lisp/emacs-lisp/eieio.el (defclass):
Obey the new `warn` value of `eieio-backward-compatibility` in
accessors to class slots.
(make-instance): Remove backward compatibility when
`eieio-backward-compatibility` is nil and emit
a warning if `eieio-backward-compatibility` is `warn`.
(clone): Obey the new `warn` value of `eieio-backward-compatibility`.
---
 etc/NEWS                      |  8 ++++++++
 lisp/emacs-lisp/eieio-base.el |  6 ++++--
 lisp/emacs-lisp/eieio-core.el |  8 ++++++--
 lisp/emacs-lisp/eieio.el      | 13 ++++++++-----
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 63957628b98..bc8871cd581 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -535,6 +535,14 @@ This variable has no effect when Transient Mark mode is off.
 
 * Changes in Specialized Modes and Packages in Emacs 31.1
 
+** EIEIO
+---
+*** New value 'warn' for 'eieio-backward-compatibility'.
+This is the new default value and causes warnings to be emitted
+at run-time for the use of the associated deprecated features.
+(setq eieio-backward-compatibility t) can be used to recover
+the previous silence.
+
 ---
 ** Text mode
 
diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el
index 7975cdf280d..31f40bb8ca1 100644
--- a/lisp/emacs-lisp/eieio-base.el
+++ b/lisp/emacs-lisp/eieio-base.el
@@ -207,9 +207,9 @@ clone
     nobj))
 
 (cl-defmethod make-instance ((class (subclass eieio-named)) &rest args)
-  (if (not (stringp (car args)))
+  (if (not (and eieio-backward-compatibility (stringp (car args))))
       (cl-call-next-method)
-    (funcall (if eieio-backward-compatibility #'ignore #'message)
+    (funcall (if (eq eieio-backward-compatibility 'warn) #'message #'ignore)
              "Obsolete: name passed without :object-name to %S constructor"
              class)
     (apply #'cl-call-next-method class :object-name args)))
@@ -345,6 +345,8 @@ eieio-persistent-make-instance
                   (object-of-class-p newobj 'eieio-named)
                   (not (oref newobj object-name))
                   name)
+         (when (eq eieio-backward-compatibility 'warn)
+           (message "Obsolete name slot initialized for %S" newobj))
          (oset newobj object-name name))
 
        newobj))))
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index 99f8feb9644..7d0fd643056 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -63,12 +63,14 @@ eieio-skip-typecheck
 (defvar eieio-optimize-primary-methods-flag t
   "Non-nil means to optimize the method dispatch on primary methods.")
 
-(defvar eieio-backward-compatibility t
+(defvar eieio-backward-compatibility 'warn
   "If nil, drop support for some behaviors of older versions of EIEIO.
 Currently under control of this var:
 - Define every class as a var whose value is the class symbol.
 - Define <class>-child-p and <class>-list-p predicates.
-- Allow object names in constructors.")
+- Allow object names in constructors.
+When `warn', also emit warnings at run-time when code uses those
+deprecated features.")
 
 (define-obsolete-variable-alias 'eieio-unbound 'eieio--unbound "28.1")
 (defvar eieio--unbound (make-symbol "eieio--unbound")
@@ -359,6 +361,8 @@ eieio-defclass-internal
              (internal--format-docstring-line
               "Test OBJ to see if it a list of objects which are a child of type `%s'."
               cname))
+            (when (eq eieio-backward-compatibility 'warn)
+              (message "Use of obsolete function %S" csym))
             (when (listp obj)
               (let ((ans t)) ;; nil is valid
                 ;; Loop over all the elements of the input list, test
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index d66915260c8..37233677d89 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -216,6 +216,9 @@ defclass
                         "Retrieve the class slot `%S' from a class `%S'."
                         sname name)
                        "\nThis method is obsolete.")
+                     (when (eq eieio-backward-compatibility 'warn)
+                       (message "Use of obsolete method %S on %S"
+                                ',acces '(subclass ,name)))
                      (if (slot-boundp this ',sname)
                          (eieio-oref-default this ',sname)))
                   accessors)))
@@ -732,10 +735,10 @@ make-instance
 calls `initialize-instance' on that object."
   (let* ((new-object (copy-sequence (eieio--class-default-object-cache
                                      (eieio--class-object class)))))
-    (if (and slots
+    (if (and slots eieio-backward-compatibility
              (let ((x (car slots)))
                (or (stringp x) (null x))))
-        (funcall (if eieio-backward-compatibility #'ignore #'message)
+        (funcall (if (eq eieio-backward-compatibility 'warn) #'message #'ignore)
                  "Obsolete name argument %S passed to %S constructor"
                  (pop slots) class))
     ;; Call the initialize method on the new object with the slots
@@ -841,9 +844,9 @@ clone
 (cl-defmethod clone ((obj eieio-default-superclass) &rest params)
   "Make a copy of OBJ, and then apply PARAMS."
   (let ((nobj (copy-sequence obj)))
-    (if (stringp (car params))
-        (funcall (if eieio-backward-compatibility #'ignore #'message)
-                 "Obsolete name argument %S passed to clone" (pop params)))
+    (if (and (stringp (car params))
+             (memq eieio-backward-compatibility '(nil warn)))
+        (message "Obsolete name argument %S passed to clone" (pop params)))
     (if params (shared-initialize nobj params))
     nobj))
 
-- 
2.47.2