aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2015-01-18 12:24:43 -0500
committerStefan Monnier2015-01-18 12:24:43 -0500
commit2a61bd0096db23123734db439051c859e42b9606 (patch)
tree95bf8383ee904cf723e57d1560f86fc551fb139b
parent8ab85ee7ce9ad101583620e7ba3bee39cf3491ae (diff)
downloademacs-2a61bd0096db23123734db439051c859e42b9606.tar.gz
emacs-2a61bd0096db23123734db439051c859e42b9606.zip
EIEIO&cl-generic: Add obsolescence warnings and fix corner case
* lisp/emacs-lisp/cl-generic.el (cl-generic-define-method): Correctly handle introduction of a new dispatch argument. (cl--generic-cache-miss): Handle dispatch on an argument which was not considered as dispatchable for this method. (cl-defmethod): Warn when adding a method to an obsolete generic function. (cl--generic-lambda): Make sure it works if cl-lib is not yet loaded. * lisp/emacs-lisp/eieio-generic.el (eieio--defgeneric-init-form): Use autoloadp. * lisp/emacs-lisp/eieio.el (defclass): Add obsolescence warning for the `newname' argument. * test/automated/cl-generic-tests.el (cl-generic-test-10-weird): New test. Rename other tests to preserve ordering.
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/ChangeLog20
-rw-r--r--lisp/emacs-lisp/cl-generic.el27
-rw-r--r--lisp/emacs-lisp/eieio-generic.el2
-rw-r--r--lisp/emacs-lisp/eieio.el11
-rw-r--r--test/ChangeLog5
-rw-r--r--test/automated/cl-generic-tests.el31
7 files changed, 75 insertions, 23 deletions
diff --git a/etc/NEWS b/etc/NEWS
index be283bbc1c3..4551c9c6b79 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -203,6 +203,8 @@ the old behavior -- *shell* buffer displays in current window -- use
203 203
204** EIEIO 204** EIEIO
205*** The `:protection' slot option is not obeyed any more. 205*** The `:protection' slot option is not obeyed any more.
206*** The `newname' argument to constructors is optional&deprecated.
207If you need your objects to be named, do it by inheriting from `eieio-named'.
206*** The <class>-list-p and <class>-child-p functions are declared obsolete. 208*** The <class>-list-p and <class>-child-p functions are declared obsolete.
207*** The <class> variables are declared obsolete. 209*** The <class> variables are declared obsolete.
208*** The <initarg> variables are declared obsolete. 210*** The <initarg> variables are declared obsolete.
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index b7a1fb943a3..c731551f913 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,6 +1,20 @@
12015-01-18 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * emacs-lisp/eieio.el (defclass): Add obsolescence warning for the
4 `newname' argument.
5
6 * emacs-lisp/cl-generic.el (cl-generic-define-method): Correctly handle
7 introduction of a new dispatch argument.
8 (cl--generic-cache-miss): Handle dispatch on an argument which was not
9 considered as dispatchable for this method.
10 (cl-defmethod): Warn when adding a method to an obsolete generic function.
11 (cl--generic-lambda): Make sure it works if cl-lib is not yet loaded.
12
13 * emacs-lisp/eieio-generic.el (eieio--defgeneric-init-form): Use autoloadp.
14
12015-01-18 Artur Malabarba <bruce.connor.am@gmail.com> 152015-01-18 Artur Malabarba <bruce.connor.am@gmail.com>
2 16
3 * emacs-lisp/package.el (package--append-to-alist): Renamed from 17 * emacs-lisp/package.el (package--append-to-alist): Rename from
4 `package--add-to-alist' 18 `package--add-to-alist'
5 Updated docstring due to new name. 19 Updated docstring due to new name.
6 20
@@ -862,8 +876,8 @@
8622014-12-27 Eli Zaretskii <eliz@gnu.org> 8762014-12-27 Eli Zaretskii <eliz@gnu.org>
863 877
864 * language/misc-lang.el (composition-function-table): Add Syriac 878 * language/misc-lang.el (composition-function-table): Add Syriac
865 characters and also ZWJ/ZWNJ. See 879 characters and also ZWJ/ZWNJ.
866 http://lists.gnu.org/archive/html/help-gnu-emacs/2014-12/msg00248.html 880 See http://lists.gnu.org/archive/html/help-gnu-emacs/2014-12/msg00248.html
867 for the details. 881 for the details.
868 882
8692014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> 8832014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org>
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 819e2e92888..544f1fa140f 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -212,13 +212,13 @@ This macro can only be used within the lexical scope of a cl-generic method."
212 (macroenv (cons `(cl-generic-current-method-specializers 212 (macroenv (cons `(cl-generic-current-method-specializers
213 . ,(lambda () specializers)) 213 . ,(lambda () specializers))
214 macroexpand-all-environment))) 214 macroexpand-all-environment)))
215 (require 'cl-lib) ;Needed to expand `cl-flet' and `cl-function'.
215 (if (not with-cnm) 216 (if (not with-cnm)
216 (cons nil (macroexpand-all fun macroenv)) 217 (cons nil (macroexpand-all fun macroenv))
217 ;; First macroexpand away the cl-function stuff (e.g. &key and 218 ;; First macroexpand away the cl-function stuff (e.g. &key and
218 ;; destructuring args, `declare' and whatnot). 219 ;; destructuring args, `declare' and whatnot).
219 (pcase (macroexpand fun macroenv) 220 (pcase (macroexpand fun macroenv)
220 (`#'(lambda ,args . ,body) 221 (`#'(lambda ,args . ,body)
221 (require 'cl-lib) ;Needed to expand `cl-flet'.
222 (let* ((doc-string (and doc-string (stringp (car body)) 222 (let* ((doc-string (and doc-string (stringp (car body))
223 (pop body))) 223 (pop body)))
224 (cnm (make-symbol "cl--cnm")) 224 (cnm (make-symbol "cl--cnm"))
@@ -287,6 +287,13 @@ which case this method will be invoked when the argument is `eql' to VAL.
287 (cadr name)))) 287 (cadr name))))
288 (setq name setter) 288 (setq name setter)
289 code)) 289 code))
290 ,(and (get name 'byte-obsolete-info)
291 (or (not (fboundp 'byte-compile-warning-enabled-p))
292 (byte-compile-warning-enabled-p 'obsolete))
293 (let* ((obsolete (get name 'byte-obsolete-info)))
294 (macroexp--warn-and-return
295 (macroexp--obsolete-warning name obsolete "generic function")
296 nil)))
290 (cl-generic-define-method ',name ',qualifiers ',args 297 (cl-generic-define-method ',name ',qualifiers ',args
291 ,uses-cnm ,fun))))) 298 ,uses-cnm ,fun)))))
292 299
@@ -308,13 +315,14 @@ which case this method will be invoked when the argument is `eql' to VAL.
308 (dolist (specializer specializers) 315 (dolist (specializer specializers)
309 (let* ((tagcode (funcall cl-generic-tagcode-function specializer 'arg)) 316 (let* ((tagcode (funcall cl-generic-tagcode-function specializer 'arg))
310 (x (assq i dispatches))) 317 (x (assq i dispatches)))
311 (if (not x) 318 (unless x
312 (setf (cl--generic-dispatches generic) 319 (setq x (list i (funcall cl-generic-tagcode-function t 'arg)))
313 (setq dispatches (cons (list i tagcode) dispatches))) 320 (setf (cl--generic-dispatches generic)
314 (unless (member tagcode (cdr x)) 321 (setq dispatches (cons x dispatches))))
315 (setf (cdr x) 322 (unless (member tagcode (cdr x))
316 (nreverse (sort (cons tagcode (cdr x)) 323 (setf (cdr x)
317 #'car-less-than-car))))) 324 (nreverse (sort (cons tagcode (cdr x))
325 #'car-less-than-car))))
318 (setq i (1+ i)))) 326 (setq i (1+ i))))
319 (if me (setcdr me (cons uses-cnm function)) 327 (if me (setcdr me (cons uses-cnm function))
320 (setf (cl--generic-method-table generic) 328 (setf (cl--generic-method-table generic)
@@ -478,7 +486,8 @@ for all those different tags in the method-cache.")
478 (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags))) 486 (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags)))
479 (methods '())) 487 (methods '()))
480 (dolist (method-desc (cl--generic-method-table generic)) 488 (dolist (method-desc (cl--generic-method-table generic))
481 (let ((m (member (nth dispatch-arg (caar method-desc)) types))) 489 (let* ((specializer (or (nth dispatch-arg (caar method-desc)) t))
490 (m (member specializer types)))
482 (when m 491 (when m
483 (push (cons (length m) method-desc) methods)))) 492 (push (cons (length m) method-desc) methods))))
484 ;; Sort the methods, most specific first. 493 ;; Sort the methods, most specific first.
diff --git a/lisp/emacs-lisp/eieio-generic.el b/lisp/emacs-lisp/eieio-generic.el
index 27a58493905..74ecefe7863 100644
--- a/lisp/emacs-lisp/eieio-generic.el
+++ b/lisp/emacs-lisp/eieio-generic.el
@@ -110,7 +110,7 @@ Methods with only primary implementations are executed in an optimized way."
110 110
111 (cond 111 (cond
112 ((or (not (fboundp method)) 112 ((or (not (fboundp method))
113 (eq 'autoload (car-safe (symbol-function method)))) 113 (autoloadp (symbol-function method)))
114 ;; Make sure the method tables are installed. 114 ;; Make sure the method tables are installed.
115 (eieio--mt-install method) 115 (eieio--mt-install method)
116 ;; Construct the actual body of this function. 116 ;; Construct the actual body of this function.
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index c5597b83170..0c85d90151a 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -276,6 +276,17 @@ and reference them using the function `class-option'."
276 `(defun ,name (&rest slots) 276 `(defun ,name (&rest slots)
277 ,(format "Create a new object with name NAME of class type %S." 277 ,(format "Create a new object with name NAME of class type %S."
278 name) 278 name)
279 (declare (compiler-macro
280 (lambda (whole)
281 (if (not (stringp (car slots)))
282 whole
283 (macroexp--warn-and-return
284 (format "Obsolete name arg %S to constructor %S"
285 (car slots) (car whole))
286 ;; Keep the name arg, for backward compatibility,
287 ;; but hide it so we don't trigger indefinitely.
288 `(,(car whole) (identity ,(car slots))
289 ,@(cdr slots)))))))
279 (apply #'eieio-constructor ',name slots)))))) 290 (apply #'eieio-constructor ',name slots))))))
280 291
281 292
diff --git a/test/ChangeLog b/test/ChangeLog
index 15baf866f37..e81bfa7d185 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
12015-01-18 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * automated/cl-generic-tests.el (cl-generic-test-10-weird): New test.
4 Rename other tests to preserve ordering.
5
12015-01-18 Leo Liu <sdl.web@gmail.com> 62015-01-18 Leo Liu <sdl.web@gmail.com>
2 7
3 * automated/seq-tests.el (test-seq-subseq): Add more tests. 8 * automated/seq-tests.el (test-seq-subseq): Add more tests.
diff --git a/test/automated/cl-generic-tests.el b/test/automated/cl-generic-tests.el
index 46397fb7f51..1c01d9b164b 100644
--- a/test/automated/cl-generic-tests.el
+++ b/test/automated/cl-generic-tests.el
@@ -29,12 +29,12 @@
29(cl-defgeneric cl--generic-1 (x y)) 29(cl-defgeneric cl--generic-1 (x y))
30(cl-defgeneric (setf cl--generic-1) (v y z) "My generic doc.") 30(cl-defgeneric (setf cl--generic-1) (v y z) "My generic doc.")
31 31
32(ert-deftest cl-generic-test-0 () 32(ert-deftest cl-generic-test-00 ()
33 (cl-defgeneric cl--generic-1 (x y)) 33 (cl-defgeneric cl--generic-1 (x y))
34 (cl-defmethod cl--generic-1 ((x t) y) (cons x y)) 34 (cl-defmethod cl--generic-1 ((x t) y) (cons x y))
35 (should (equal (cl--generic-1 'a 'b) '(a . b)))) 35 (should (equal (cl--generic-1 'a 'b) '(a . b))))
36 36
37(ert-deftest cl-generic-test-1-eql () 37(ert-deftest cl-generic-test-01-eql ()
38 (cl-defgeneric cl--generic-1 (x y)) 38 (cl-defgeneric cl--generic-1 (x y))
39 (cl-defmethod cl--generic-1 ((x t) y) (cons x y)) 39 (cl-defmethod cl--generic-1 ((x t) y) (cons x y))
40 (cl-defmethod cl--generic-1 ((_x (eql 4)) _y) 40 (cl-defmethod cl--generic-1 ((_x (eql 4)) _y)
@@ -53,7 +53,7 @@
53(cl-defstruct (cl-generic-struct-child11 (:include cl-generic-struct-child1)) d) 53(cl-defstruct (cl-generic-struct-child11 (:include cl-generic-struct-child1)) d)
54(cl-defstruct (cl-generic-struct-child2 (:include cl-generic-struct-parent)) e) 54(cl-defstruct (cl-generic-struct-child2 (:include cl-generic-struct-parent)) e)
55 55
56(ert-deftest cl-generic-test-2-struct () 56(ert-deftest cl-generic-test-02-struct ()
57 (cl-defgeneric cl--generic-1 (x y) "My doc.") 57 (cl-defgeneric cl--generic-1 (x y) "My doc.")
58 (cl-defmethod cl--generic-1 ((x t) y) "Doc 1." (cons x y)) 58 (cl-defmethod cl--generic-1 ((x t) y) "Doc 1." (cons x y))
59 (cl-defmethod cl--generic-1 ((_x cl-generic-struct-parent) y) 59 (cl-defmethod cl--generic-1 ((_x cl-generic-struct-parent) y)
@@ -73,7 +73,7 @@
73 (should (equal (cl--generic-1 (make-cl-generic-struct-child11) nil) 73 (should (equal (cl--generic-1 (make-cl-generic-struct-child11) nil)
74 '("child11" "around""child1" "parent" a)))) 74 '("child11" "around""child1" "parent" a))))
75 75
76(ert-deftest cl-generic-test-3-setf () 76(ert-deftest cl-generic-test-03-setf ()
77 (cl-defmethod (setf cl--generic-1) (v (y t) z) (list v y z)) 77 (cl-defmethod (setf cl--generic-1) (v (y t) z) (list v y z))
78 (cl-defmethod (setf cl--generic-1) (v (_y (eql 4)) z) (list v "four" z)) 78 (cl-defmethod (setf cl--generic-1) (v (_y (eql 4)) z) (list v "four" z))
79 (should (equal (setf (cl--generic-1 'a 'b) 'v) '(v a b))) 79 (should (equal (setf (cl--generic-1 'a 'b) 'v) '(v a b)))
@@ -85,7 +85,7 @@
85 '(v a b))) 85 '(v a b)))
86 (should (equal x '(3 2 1))))) 86 (should (equal x '(3 2 1)))))
87 87
88(ert-deftest cl-generic-test-4-overlapping-tagcodes () 88(ert-deftest cl-generic-test-04-overlapping-tagcodes ()
89 (cl-defgeneric cl--generic-1 (x y) "My doc.") 89 (cl-defgeneric cl--generic-1 (x y) "My doc.")
90 (cl-defmethod cl--generic-1 ((y t) z) (list y z)) 90 (cl-defmethod cl--generic-1 ((y t) z) (list y z))
91 (cl-defmethod cl--generic-1 ((_y (eql 4)) _z) 91 (cl-defmethod cl--generic-1 ((_y (eql 4)) _z)
@@ -98,7 +98,7 @@
98 (should (equal (cl--generic-1 1 'b) '("integer" "number" 1 b))) 98 (should (equal (cl--generic-1 1 'b) '("integer" "number" 1 b)))
99 (should (equal (cl--generic-1 4 'b) '("four" "integer" "number" 4 b)))) 99 (should (equal (cl--generic-1 4 'b) '("four" "integer" "number" 4 b))))
100 100
101(ert-deftest cl-generic-test-5-alias () 101(ert-deftest cl-generic-test-05-alias ()
102 (cl-defgeneric cl--generic-1 (x y) "My doc.") 102 (cl-defgeneric cl--generic-1 (x y) "My doc.")
103 (defalias 'cl--generic-2 #'cl--generic-1) 103 (defalias 'cl--generic-2 #'cl--generic-1)
104 (cl-defmethod cl--generic-1 ((y t) z) (list y z)) 104 (cl-defmethod cl--generic-1 ((y t) z) (list y z))
@@ -106,7 +106,7 @@
106 (cons "four" (cl-call-next-method))) 106 (cons "four" (cl-call-next-method)))
107 (should (equal (cl--generic-1 4 'b) '("four" 4 b)))) 107 (should (equal (cl--generic-1 4 'b) '("four" 4 b))))
108 108
109(ert-deftest cl-generic-test-6-multiple-dispatch () 109(ert-deftest cl-generic-test-06-multiple-dispatch ()
110 (cl-defgeneric cl--generic-1 (x y) "My doc.") 110 (cl-defgeneric cl--generic-1 (x y) "My doc.")
111 (cl-defmethod cl--generic-1 (x y) (list x y)) 111 (cl-defmethod cl--generic-1 (x y) (list x y))
112 (cl-defmethod cl--generic-1 (_x (_y integer)) 112 (cl-defmethod cl--generic-1 (_x (_y integer))
@@ -117,7 +117,7 @@
117 (cons "x&y-int" (cl-call-next-method))) 117 (cons "x&y-int" (cl-call-next-method)))
118 (should (equal (cl--generic-1 1 2) '("x&y-int" "x-int" "y-int" 1 2)))) 118 (should (equal (cl--generic-1 1 2) '("x&y-int" "x-int" "y-int" 1 2))))
119 119
120(ert-deftest cl-generic-test-7-apo () 120(ert-deftest cl-generic-test-07-apo ()
121 (cl-defgeneric cl--generic-1 (x y) 121 (cl-defgeneric cl--generic-1 (x y)
122 (:documentation "My doc.") (:argument-precedence-order y x)) 122 (:documentation "My doc.") (:argument-precedence-order y x))
123 (cl-defmethod cl--generic-1 (x y) (list x y)) 123 (cl-defmethod cl--generic-1 (x y) (list x y))
@@ -129,7 +129,7 @@
129 (cons "x&y-int" (cl-call-next-method))) 129 (cons "x&y-int" (cl-call-next-method)))
130 (should (equal (cl--generic-1 1 2) '("x&y-int" "y-int" "x-int" 1 2)))) 130 (should (equal (cl--generic-1 1 2) '("x&y-int" "y-int" "x-int" 1 2))))
131 131
132(ert-deftest cl-generic-test-8-after/before () 132(ert-deftest cl-generic-test-08-after/before ()
133 (let ((log ())) 133 (let ((log ()))
134 (cl-defgeneric cl--generic-1 (x y)) 134 (cl-defgeneric cl--generic-1 (x y))
135 (cl-defmethod cl--generic-1 ((_x t) y) (cons y log)) 135 (cl-defmethod cl--generic-1 ((_x t) y) (cons y log))
@@ -144,7 +144,7 @@
144 144
145(defun cl--generic-test-advice (&rest args) (cons "advice" (apply args))) 145(defun cl--generic-test-advice (&rest args) (cons "advice" (apply args)))
146 146
147(ert-deftest cl-generic-test-9-advice () 147(ert-deftest cl-generic-test-09-advice ()
148 (cl-defgeneric cl--generic-1 (x y) "My doc.") 148 (cl-defgeneric cl--generic-1 (x y) "My doc.")
149 (cl-defmethod cl--generic-1 (x y) (list x y)) 149 (cl-defmethod cl--generic-1 (x y) (list x y))
150 (advice-add 'cl--generic-1 :around #'cl--generic-test-advice) 150 (advice-add 'cl--generic-1 :around #'cl--generic-test-advice)
@@ -155,5 +155,16 @@
155 (advice-remove 'cl--generic-1 #'cl--generic-test-advice) 155 (advice-remove 'cl--generic-1 #'cl--generic-test-advice)
156 (should (equal (cl--generic-1 4 5) '("integer" 4 5)))) 156 (should (equal (cl--generic-1 4 5) '("integer" 4 5))))
157 157
158(ert-deftest cl-generic-test-10-weird ()
159 (cl-defgeneric cl--generic-1 (x &rest r) "My doc.")
160 (cl-defmethod cl--generic-1 (x &rest r) (cons x r))
161 ;; This kind of definition is not valid according to CLHS, but it does show
162 ;; up in EIEIO's tests for no-next-method, so we should either
163 ;; detect it and signal an error or do something meaningful with it.
164 (cl-defmethod cl--generic-1 (x (y integer) &rest r)
165 `("integer" ,y ,x ,@r))
166 (should (equal (cl--generic-1 'a 'b) '(a b)))
167 (should (equal (cl--generic-1 1 2) '("integer" 2 1))))
168
158(provide 'cl-generic-tests) 169(provide 'cl-generic-tests)
159;;; cl-generic-tests.el ends here 170;;; cl-generic-tests.el ends here