From b939f7ad359807e846831a9854e0d94260d9f084 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 14 Feb 2021 21:13:35 -0500 Subject: * Edebug: Generalize `&lookup`, use it for `cl-macrolet` and `cl-generic` This allows the use of (declare (debug ...)) in the lexical macros defined with `cl-macrolet`. It also fixes the names used by Edebug for the methods of `cl-generic` so it doesn't need to use gensym and so they don't include the formal arg names any more. * lisp/emacs-lisp/edebug.el (edebug--match-&-spec-op): Rename from `edebug--handle-&-spec-op`. (edebug--match-&-spec-op <&interpose>): Rename from `&lookup` and generalize so it can let-bind dynamic variables around the rest of the parse. (edebug-lexical-macro-ctx): Rename from `edebug--cl-macrolet-defs` and make it into an alist. (edebug-list-form-args): Use the specs from `edebug-lexical-macro-ctx` when available. (edebug--current-cl-macrolet-defs): Delete var. (edebug-match-cl-macrolet-expr, edebug-match-cl-macrolet-name) (edebug-match-cl-macrolet-body): Delete functions. (def-declarations): Use new `&interpose`. (edebug--match-declare-arg): Rename from `edebug--get-declare-spec` and adjust to new calling convention. * lisp/subr.el (def-edebug-elem-spec): Fix docstring. (eval-after-load): Use `declare`. * lisp/emacs-lisp/cl-generic.el: Fix Edebug names so we don't need gensym any more and we only include the specializers but not the formal arg names. (cl--generic-edebug-name): New var. (cl--generic-edebug-remember-name, cl--generic-edebug-make-name): New funs. (cl-defgeneric, cl-defmethod): Use them. * lisp/emacs-lisp/cl-macs.el: Add support for `debug` declarations in `cl-macrolet`. (cl-declarations-or-string): Fix use of `lambda-doc` and allow use of `declare`. (edebug-lexical-macro-ctx): Declare var. (cl--edebug-macrolet-interposer): New function. (cl-macrolet): Use it to pass the right `lexical-macro-ctx` to the body. * lisp/emacs-lisp/pcase.el (pcase-PAT): Use new `&interpose`. (pcase--edebug-match-pat-args): Rename from `pcase--get-edebug-spec` and adjust to new calling convention. * test/lisp/emacs-lisp/cl-generic-tests.el (cl-defgeneric/edebug/method): Adjust to the new names. * test/lisp/emacs-lisp/edebug-tests.el (edebug-cl-defmethod-qualifier) (edebug-tests-cl-flet): Adjust to the new names. * doc/lispref/edebug.texi (Specification List): Document &interpose. --- test/lisp/emacs-lisp/cl-generic-tests.el | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'test/lisp/emacs-lisp/cl-generic-tests.el') diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index 4a01623cb88..9312fb44a1e 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -269,9 +269,7 @@ Edebug symbols (Bug#42672)." (when (memq name instrumented-names) (error "Duplicate definition of `%s'" name)) (push name instrumented-names) - (edebug-new-definition name))) - ;; Make generated symbols reproducible. - (gensym-counter 10000)) + (edebug-new-definition name)))) (eval-buffer) (should (equal (reverse instrumented-names) @@ -280,11 +278,11 @@ Edebug symbols (Bug#42672)." ;; FIXME: We'd rather have names such as ;; `cl-defgeneric/edebug/method/1 ((_ number))', but ;; that requires further changes to Edebug. - (list (intern "cl-generic-:method@10000 ((_ number))") - (intern "cl-generic-:method@10001 ((_ string))") - (intern "cl-generic-:method@10002 :around ((_ number))") + (list (intern "cl-defgeneric/edebug/method/1 (number)") + (intern "cl-defgeneric/edebug/method/1 (string)") + (intern "cl-defgeneric/edebug/method/1 :around (number)") 'cl-defgeneric/edebug/method/1 - (intern "cl-generic-:method@10003 ((_ number))") + (intern "cl-defgeneric/edebug/method/2 (number)") 'cl-defgeneric/edebug/method/2)))))) (provide 'cl-generic-tests) -- cgit v1.2.3 From 6535fd1fa9ac21238a168916249ac59677a6118e Mon Sep 17 00:00:00 2001 From: akater Date: Tue, 20 Jul 2021 01:25:01 +0000 Subject: Evaluate eql specializers * lisp/emacs-lisp/cl-generic.el (cl-generic-generalizers): Evaluate forms that are eql specializers. Provide backward compatibility with a warning. * test/lisp/emacs-lisp/cl-generic-tests.el: Add a test. * lisp/emacs-lisp/bindat.el (bindat--type): Adhere to the new rule. * lisp/emacs-lisp/edebug.el (edebug--match-&-spec-op): Adhere to the new rule. * lisp/emacs-lisp/map.el (map-into): Adhere to the new rule. * lisp/emacs-lisp/radix-tree.el (map-into): Adhere to the new rule. * lisp/frame.el (cl-generic-define-context-rewriter): Adhere to the new rule. * lisp/gnus/gnus-search.el (gnus-search-transform-expression): Adhere to the new rule. * lisp/image/image-converter.el (image-converter--probe image-converter--convert): Adhere to the new rule. * lisp/mail/smtpmail.el (smtpmail-try-auth-method): Adhere to the new rule. * lisp/progmodes/elisp-mode.el (xref-backend-definitions) (xref-backend-apropos): Adhere to the new rule. * lisp/progmodes/etags.el (xref-backend-identifier-at-point) (xref-backend-identifier-completion-table) (xref-backend-identifier-completion-ignore-case) (xref-backend-definitions)(xref-backend-apropos): Adhere to the new rule. * test/lisp/emacs-lisp/checkdoc-tests.el (checkdoc-cl-defmethod-with-types-ok) (checkdoc-cl-defmethod-qualified-ok) (checkdoc-cl-defmethod-with-extra-qualifier-ok): Adhere to the new rule. * etc/NEWS: Describe the change. --- etc/NEWS | 5 +++++ lisp/emacs-lisp/bindat.el | 24 ++++++++++++------------ lisp/emacs-lisp/cl-generic.el | 12 +++++++++++- lisp/emacs-lisp/edebug.el | 18 +++++++++--------- lisp/emacs-lisp/map.el | 8 ++++---- lisp/emacs-lisp/radix-tree.el | 2 +- lisp/frame.el | 6 +++++- lisp/gnus/gnus-search.el | 2 +- lisp/image/image-converter.el | 12 ++++++------ lisp/mail/smtpmail.el | 6 +++--- lisp/progmodes/elisp-mode.el | 7 ++++--- lisp/progmodes/etags.el | 12 +++++++----- test/lisp/emacs-lisp/checkdoc-tests.el | 8 ++++---- test/lisp/emacs-lisp/cl-generic-tests.el | 6 +++++- 14 files changed, 77 insertions(+), 51 deletions(-) (limited to 'test/lisp/emacs-lisp/cl-generic-tests.el') diff --git a/etc/NEWS b/etc/NEWS index 48dec0a2b3b..fb6eddc754f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -810,6 +810,11 @@ work as before. It is now defined as a generalized variable that can be used with 'setf' to modify the value stored in a given class slot. +--- +*** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated. +This corresponds to the behaviour of defmethod in Common Lisp Object System. +A warning is issued when old style is used. + ** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'. The mode provides refined highlighting of built-in functions, types, and variables. diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 247fb91379e..76c2e80fda8 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -657,33 +657,33 @@ The port (if any) is omitted. IP can be a string, as well." OP can be one of: unpack', (pack VAL), or (length VAL) where VAL is the name of a variable that will hold the value we need to pack.") -(cl-defmethod bindat--type (op (_ (eql byte))) +(cl-defmethod bindat--type (op (_ (eql 'byte))) (bindat--pcase op ('unpack `(bindat--unpack-u8)) (`(length . ,_) `(cl-incf bindat-idx 1)) (`(pack . ,args) `(bindat--pack-u8 . ,args)))) -(cl-defmethod bindat--type (op (_ (eql uint)) n) +(cl-defmethod bindat--type (op (_ (eql 'uint)) n) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op ('unpack `(bindat--unpack-uint ,n)) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) (`(pack . ,args) `(bindat--pack-uint ,n . ,args))))) -(cl-defmethod bindat--type (op (_ (eql uintr)) n) +(cl-defmethod bindat--type (op (_ (eql 'uintr)) n) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op ('unpack `(bindat--unpack-uintr ,n)) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) (`(pack . ,args) `(bindat--pack-uintr ,n . ,args))))) -(cl-defmethod bindat--type (op (_ (eql str)) len) +(cl-defmethod bindat--type (op (_ (eql 'str)) len) (bindat--pcase op ('unpack `(bindat--unpack-str ,len)) (`(length . ,_) `(cl-incf bindat-idx ,len)) (`(pack . ,args) `(bindat--pack-str ,len . ,args)))) -(cl-defmethod bindat--type (op (_ (eql strz)) &optional len) +(cl-defmethod bindat--type (op (_ (eql 'strz)) &optional len) (bindat--pcase op ('unpack `(bindat--unpack-strz ,len)) (`(length ,val) @@ -701,25 +701,25 @@ is the name of a variable that will hold the value we need to pack.") (bindat--pack-str ,len . ,args) (bindat--pack-strz . ,args)))))) -(cl-defmethod bindat--type (op (_ (eql bits)) len) +(cl-defmethod bindat--type (op (_ (eql 'bits)) len) (bindat--pcase op ('unpack `(bindat--unpack-bits ,len)) (`(length . ,_) `(cl-incf bindat-idx ,len)) (`(pack . ,args) `(bindat--pack-bits ,len . ,args)))) -(cl-defmethod bindat--type (_op (_ (eql fill)) len) +(cl-defmethod bindat--type (_op (_ (eql 'fill)) len) `(progn (cl-incf bindat-idx ,len) nil)) -(cl-defmethod bindat--type (_op (_ (eql align)) len) +(cl-defmethod bindat--type (_op (_ (eql 'align)) len) `(progn (cl-callf bindat--align bindat-idx ,len) nil)) -(cl-defmethod bindat--type (op (_ (eql type)) exp) +(cl-defmethod bindat--type (op (_ (eql 'type)) exp) (bindat--pcase op ('unpack `(funcall (bindat--type-ue ,exp))) (`(length . ,args) `(funcall (bindat--type-le ,exp) . ,args)) (`(pack . ,args) `(funcall (bindat--type-pe ,exp) . ,args)))) -(cl-defmethod bindat--type (op (_ (eql vec)) count &rest type) +(cl-defmethod bindat--type (op (_ (eql 'vec)) count &rest type) (unless type (setq type '(byte))) (let ((fun (macroexpand-all (bindat--fun type) macroexpand-all-environment))) (bindat--pcase op @@ -743,10 +743,10 @@ is the name of a variable that will hold the value we need to pack.") `(dotimes (bindat--i ,count) (funcall ,fun (elt ,val bindat--i))))))) -(cl-defmethod bindat--type (op (_ (eql unit)) val) +(cl-defmethod bindat--type (op (_ (eql 'unit)) val) (pcase op ('unpack val) (_ nil))) -(cl-defmethod bindat--type (op (_ (eql struct)) &rest args) +(cl-defmethod bindat--type (op (_ (eql 'struct)) &rest args) (apply #'bindat--type op args)) (cl-defmethod bindat--type (op (_ (eql :pack-var)) var &rest fields) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 544704be387..941e436ff78 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1158,7 +1158,12 @@ These match if the argument is a cons cell whose car is `eql' to VAL." (cl-defmethod cl-generic-generalizers ((specializer (head eql))) "Support for (eql VAL) specializers. These match if the argument is `eql' to VAL." - (puthash (cadr specializer) specializer cl--generic-eql-used) + (let ((form (cadr specializer))) + (puthash (if (or (not (symbolp form)) (macroexp-const-p form)) + (eval form t) + (message "Quoting obsolete `eql' form: %S" specializer) + form) + specializer cl--generic-eql-used)) (list cl--generic-eql-generalizer)) (cl--generic-prefill-dispatchers 0 (eql nil)) @@ -1269,6 +1274,11 @@ Used internally for the (major-mode MODE) context specializers." (cl-generic-define-context-rewriter major-mode (mode &rest modes) `(major-mode ,(if (consp mode) ;;E.g. could be (eql ...) + ;; WARNING: unsure whether this + ;; “could be (eql ...)” commentary (or code) + ;; should be adjusted + ;; following the (planned) changes to eql specializer. + ;; Bug #47327 (progn (cl-assert (null modes)) mode) `(derived-mode ,mode . ,modes)))) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 2aec8197dc9..7def9ff96a7 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1731,7 +1731,7 @@ contains a circular object." (defsubst edebug-match-body (cursor) (edebug-forms cursor)) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &optional)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&optional)) cursor specs) ;; Keep matching until one spec fails. (edebug-&optional-wrapper cursor specs #'edebug-&optional-wrapper)) @@ -1755,7 +1755,7 @@ contains a circular object." "Handle &foo spec operators. &foo spec operators operate on all the subsequent SPECS.") -(cl-defmethod edebug--match-&-spec-op ((_ (eql &rest)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&rest)) cursor specs) ;; Repeatedly use specs until failure. (let (edebug-best-error edebug-error-point) @@ -1768,7 +1768,7 @@ contains a circular object." (edebug-&optional-wrapper c (or s specs) rh))))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &or)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&or)) cursor specs) ;; Keep matching until one spec succeeds, and return its results. ;; If none match, fail. ;; This needs to be optimized since most specs spend time here. @@ -1792,7 +1792,7 @@ contains a circular object." (apply #'edebug-no-match cursor "Expected one of" original-specs)) )) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &interpose)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&interpose)) cursor specs) "Compute the specs for `&interpose SPEC FUN ARGS...'. Extracts the head of the data by matching it against SPEC, and then matches the rest by calling (FUN HEAD PF ARGS...) @@ -1817,7 +1817,7 @@ a sequence of elements." (append instrumented-head (edebug-match cursor newspecs))) ,@args)))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql ¬)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '¬)) cursor specs) ;; If any specs match, then fail (if (null (catch 'no-match (let ((edebug-gate nil)) @@ -1829,7 +1829,7 @@ a sequence of elements." ;; This means nothing matched, so it is OK. nil) ;; So, return nothing -(cl-defmethod edebug--match-&-spec-op ((_ (eql &key)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&key)) cursor specs) ;; Following specs must look like ( ) ... ;; where is the name of a keyword, and spec is its spec. ;; This really doesn't save much over the expanded form and takes time. @@ -1842,7 +1842,7 @@ a sequence of elements." (car (cdr pair)))) specs)))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &error)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&error)) cursor specs) ;; Signal an error, using the following string in the spec as argument. (let ((error-string (car specs)) (edebug-error-point (edebug-before-offset cursor))) @@ -1942,7 +1942,7 @@ a sequence of elements." (defun edebug-match-function (_cursor) (error "Use function-form instead of function in edebug spec")) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &define)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&define)) cursor specs) ;; Match a defining form. ;; Normally, &define is interpreted specially other places. ;; This should only be called inside of a spec list to match the remainder @@ -1958,7 +1958,7 @@ a sequence of elements." ;; Stop backtracking here (Bug#41988). (setq edebug-gate t))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &name)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&name)) cursor specs) "Compute the name for `&name SPEC FUN` spec operator. The full syntax of that operator is: diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index 5c76fb9eb95..c59342875db 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -407,15 +407,15 @@ See `map-into' for all supported values of TYPE." "Convert MAP into a map of TYPE.") ;; FIXME: I wish there was a way to avoid this η-redex! -(cl-defmethod map-into (map (_type (eql list))) +(cl-defmethod map-into (map (_type (eql 'list))) "Convert MAP into an alist." (map-pairs map)) -(cl-defmethod map-into (map (_type (eql alist))) +(cl-defmethod map-into (map (_type (eql 'alist))) "Convert MAP into an alist." (map-pairs map)) -(cl-defmethod map-into (map (_type (eql plist))) +(cl-defmethod map-into (map (_type (eql 'plist))) "Convert MAP into a plist." (let (plist) (map-do (lambda (k v) (setq plist `(,v ,k ,@plist))) map) @@ -510,7 +510,7 @@ KEYWORD-ARGS are forwarded to `make-hash-table'." map) ht)) -(cl-defmethod map-into (map (_type (eql hash-table))) +(cl-defmethod map-into (map (_type (eql 'hash-table))) "Convert MAP into a hash-table with keys compared with `equal'." (map--into-hash map (list :size (map-length map) :test #'equal))) diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el index fb659753501..a529ed025d6 100644 --- a/lisp/emacs-lisp/radix-tree.el +++ b/lisp/emacs-lisp/radix-tree.el @@ -240,7 +240,7 @@ PREFIX is only used internally." (declare-function map-apply "map" (function map)) (defun radix-tree-from-map (map) - ;; Aka (cl-defmethod map-into (map (type (eql radix-tree)))) ...) + ;; Aka (cl-defmethod map-into (map (type (eql 'radix-tree)))) ...) (require 'map) (let ((rt nil)) (map-apply (lambda (k v) (setq rt (radix-tree-insert rt k v))) map) diff --git a/lisp/frame.el b/lisp/frame.el index 9b3d120598b..8c05ad2fe5c 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -36,7 +36,11 @@ as its argument.") (cl-generic-define-context-rewriter window-system (value) ;; If `value' is a `consp', it's probably an old-style specializer, ;; so just use it, and anyway `eql' isn't very useful on cons cells. - `(window-system ,(if (consp value) value `(eql ,value)))) + `(window-system ,(if (consp value) value + ;; WARNING: unsure whether this eql expression + ;; is actually an eql specializer. + ;; Bug #47327 + `(eql ',value)))) (cl-defmethod frame-creation-function (params &context (window-system nil)) ;; It's tempting to get rid of tty-create-frame-with-faces and turn it into diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 39bde837b30..53af2f6fe6a 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -980,7 +980,7 @@ Responsible for handling and, or, and parenthetical expressions.") ;; Most search engines use implicit ANDs. (cl-defmethod gnus-search-transform-expression ((_ gnus-search-engine) - (_expr (eql and))) + (_expr (eql 'and))) nil) ;; Most search engines use explicit infixed ORs. diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el index e47f1f76e42..97bf1ac058c 100644 --- a/lisp/image/image-converter.el +++ b/lisp/image/image-converter.el @@ -133,7 +133,7 @@ data is returned as a string." (list value) value))) -(cl-defmethod image-converter--probe ((type (eql graphicsmagick))) +(cl-defmethod image-converter--probe ((type (eql 'graphicsmagick))) "Check whether the system has GraphicsMagick installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -151,7 +151,7 @@ data is returned as a string." (push (downcase (match-string 1)) formats))) (nreverse formats))))) -(cl-defmethod image-converter--probe ((type (eql imagemagick))) +(cl-defmethod image-converter--probe ((type (eql 'imagemagick))) "Check whether the system has ImageMagick installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -171,7 +171,7 @@ data is returned as a string." (push (downcase (match-string 1)) formats))) (nreverse formats)))) -(cl-defmethod image-converter--probe ((type (eql ffmpeg))) +(cl-defmethod image-converter--probe ((type (eql 'ffmpeg))) "Check whether the system has ffmpeg installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -212,12 +212,12 @@ Only suffixes that map to `image-mode' are returned." 'image-mode) collect suffix)) -(cl-defmethod image-converter--convert ((type (eql graphicsmagick)) source +(cl-defmethod image-converter--convert ((type (eql 'graphicsmagick)) source image-format) "Convert using GraphicsMagick." (image-converter--convert-magick type source image-format)) -(cl-defmethod image-converter--convert ((type (eql imagemagick)) source +(cl-defmethod image-converter--convert ((type (eql 'imagemagick)) source image-format) "Convert using ImageMagick." (image-converter--convert-magick type source image-format)) @@ -249,7 +249,7 @@ Only suffixes that map to `image-mode' are returned." ;; error message. (buffer-string)))) -(cl-defmethod image-converter--convert ((type (eql ffmpeg)) source +(cl-defmethod image-converter--convert ((type (eql 'ffmpeg)) source image-format) "Convert using ffmpeg." (let ((command (image-converter--value type :command))) diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index 133a2e1828e..33bdd050bdc 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el @@ -596,7 +596,7 @@ USER and PASSWORD should be non-nil." (error "Mechanism %S not implemented" mech)) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql cram-md5)) user password) + (process (_mech (eql 'cram-md5)) user password) (let ((ret (smtpmail-command-or-throw process "AUTH CRAM-MD5"))) (when (eq (car ret) 334) (let* ((challenge (substring (cadr ret) 4)) @@ -618,13 +618,13 @@ USER and PASSWORD should be non-nil." (smtpmail-command-or-throw process encoded))))) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql login)) user password) + (process (_mech (eql 'login)) user password) (smtpmail-command-or-throw process "AUTH LOGIN") (smtpmail-command-or-throw process (base64-encode-string user t)) (smtpmail-command-or-throw process (base64-encode-string password t))) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql plain)) user password) + (process (_mech (eql 'plain)) user password) ;; We used to send an empty initial request, and wait for an ;; empty response, and then send the password, but this ;; violate a SHOULD in RFC 2222 paragraph 5.1. Note that this diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7ed2d3d08cc..542f8ad0b1b 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -696,7 +696,7 @@ Each function should return a list of xrefs, or nil; the first non-nil result supersedes the xrefs produced by `elisp--xref-find-definitions'.") -(cl-defmethod xref-backend-definitions ((_backend (eql elisp)) identifier) +(cl-defmethod xref-backend-definitions ((_backend (eql 'elisp)) identifier) (require 'find-func) ;; FIXME: use information in source near point to filter results: ;; (dvc-log-edit ...) - exclude 'feature @@ -875,7 +875,7 @@ non-nil result supersedes the xrefs produced by (declare-function xref-apropos-regexp "xref" (pattern)) -(cl-defmethod xref-backend-apropos ((_backend (eql elisp)) pattern) +(cl-defmethod xref-backend-apropos ((_backend (eql 'elisp)) pattern) (apply #'nconc (let ((regexp (xref-apropos-regexp pattern)) lst) @@ -893,7 +893,8 @@ non-nil result supersedes the xrefs produced by (facep sym))) 'strict)) -(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql elisp))) +(cl-defmethod xref-backend-identifier-completion-table ((_backend + (eql 'elisp))) elisp--xref-identifier-completion-table) (cl-defstruct (xref-elisp-location diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index f0180ceeeca..ce1d8e5e620 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -2062,19 +2062,21 @@ file name, add `tag-partial-file-name-match-p' to the list value.") ;;;###autoload (defun etags--xref-backend () 'etags) -(cl-defmethod xref-backend-identifier-at-point ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-at-point ((_backend (eql 'etags))) (find-tag--default)) -(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-completion-table ((_backend + (eql 'etags))) (tags-lazy-completion-table)) -(cl-defmethod xref-backend-identifier-completion-ignore-case ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-completion-ignore-case ((_backend + (eql 'etags))) (find-tag--completion-ignore-case)) -(cl-defmethod xref-backend-definitions ((_backend (eql etags)) symbol) +(cl-defmethod xref-backend-definitions ((_backend (eql 'etags)) symbol) (etags--xref-find-definitions symbol)) -(cl-defmethod xref-backend-apropos ((_backend (eql etags)) pattern) +(cl-defmethod xref-backend-apropos ((_backend (eql 'etags)) pattern) (etags--xref-find-definitions (xref-apropos-regexp pattern) t)) (defun etags--xref-find-definitions (pattern &optional regexp?) diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el index 7a7aa9fb3cd..2a1d8b27636 100644 --- a/test/lisp/emacs-lisp/checkdoc-tests.el +++ b/test/lisp/emacs-lisp/checkdoc-tests.el @@ -49,27 +49,27 @@ (with-temp-buffer (emacs-lisp-mode) ;; this method matches if A is the symbol `smthg' and if b is a list: - (insert "(cl-defmethod foo ((a (eql smthg)) (b list)) \"Return A+B.\")") + (insert "(cl-defmethod foo ((a (eql 'smthg)) (b list)) \"Return A+B.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-qualified-ok () "Checkdoc should be happy with a `cl-defmethod' using qualifiers." (with-temp-buffer (emacs-lisp-mode) - (insert "(cl-defmethod test :around ((a (eql smthg))) \"Return A.\")") + (insert "(cl-defmethod test :around ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-ok () "Checkdoc should be happy with a :extra qualified `cl-defmethod'." (with-temp-buffer (emacs-lisp-mode) - (insert "(cl-defmethod foo :extra \"foo\" ((a (eql smthg))) \"Return A.\")") + (insert "(cl-defmethod foo :extra \"foo\" ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun)) (with-temp-buffer (emacs-lisp-mode) (insert - "(cl-defmethod foo :extra \"foo\" :after ((a (eql smthg))) \"Return A.\")") + "(cl-defmethod foo :extra \"foo\" :after ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-and-nil-args-ok () diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index 9312fb44a1e..0093b04d1d8 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -56,7 +56,11 @@ (should (equal (cl--generic-1 'a nil) '(a))) (should (equal (cl--generic-1 4 nil) '("quatre" 4))) (should (equal (cl--generic-1 5 nil) '("cinq" 5))) - (should (equal (cl--generic-1 6 nil) '("six" a)))) + (should (equal (cl--generic-1 6 nil) '("six" a))) + (defvar cl--generic-fooval 41) + (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y) + "forty-two") + (should (equal (cl--generic 42 nil) "forty-two"))) (cl-defstruct cl-generic-struct-parent a b) (cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c) -- cgit v1.2.3 From 516affe1b3c1525d49fd7fd050a42d234470b4c6 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Wed, 4 Aug 2021 06:38:34 +0200 Subject: Fix apparent typo in new cl-generic-tests.el test case --- test/lisp/emacs-lisp/cl-generic-tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/lisp/emacs-lisp/cl-generic-tests.el') diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index 0093b04d1d8..b48a48fb944 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -60,7 +60,7 @@ (defvar cl--generic-fooval 41) (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y) "forty-two") - (should (equal (cl--generic 42 nil) "forty-two"))) + (should (equal (cl--generic-1 42 nil) "forty-two"))) (cl-defstruct cl-generic-struct-parent a b) (cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c) -- cgit v1.2.3 From 75de09b9de2c800d074e2b65a03483d0d44ce3de Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 9 Aug 2021 19:03:01 -0400 Subject: * lisp/emacs-lisp/cl-generic.el: Try and fix bug#49866 (cl-generic-generalizers): Remember the specializers that match a given value. (cl--generic-eql-generalizer): Adjust accordingly. * test/lisp/emacs-lisp/cl-generic-tests.el (cl-generic-test-01-eql): Add corresponding test. --- lisp/emacs-lisp/cl-generic.el | 29 +++++++++++++++++------------ test/lisp/emacs-lisp/cl-generic-tests.el | 5 ++++- 2 files changed, 21 insertions(+), 13 deletions(-) (limited to 'test/lisp/emacs-lisp/cl-generic-tests.el') diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index db5a5a0c89a..4a69df15bc8 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1153,22 +1153,27 @@ These match if the argument is a cons cell whose car is `eql' to VAL." (cl-generic-define-generalizer cl--generic-eql-generalizer 100 (lambda (name &rest _) `(gethash ,name cl--generic-eql-used)) - (lambda (tag &rest _) (if (eq (car-safe tag) 'eql) (list tag)))) + (lambda (tag &rest _) (if (eq (car-safe tag) 'eql) (cdr tag)))) (cl-defmethod cl-generic-generalizers ((specializer (head eql))) "Support for (eql VAL) specializers. These match if the argument is `eql' to VAL." - (let ((form (cadr specializer))) - (puthash (if (or (not (symbolp form)) (macroexp-const-p form)) - (eval form t) - ;; FIXME: Compatibility with Emacs<28. For now emitting - ;; a warning would be annoying for third party packages - ;; which can't use the new form without breaking compatibility - ;; with older Emacsen, but in the future we should emit - ;; a warning. - ;; (message "Quoting obsolete `eql' form: %S" specializer) - form) - specializer cl--generic-eql-used)) + (let* ((form (cadr specializer)) + (val (if (or (not (symbolp form)) (macroexp-const-p form)) + (eval form t) + ;; FIXME: Compatibility with Emacs<28. For now emitting + ;; a warning would be annoying for third party packages + ;; which can't use the new form without breaking compatibility + ;; with older Emacsen, but in the future we should emit + ;; a warning. + ;; (message "Quoting obsolete `eql' form: %S" specializer) + form)) + (specializers (cdr (gethash val cl--generic-eql-used)))) + ;; The `specializers-function' needs to return all the (eql EXP) that + ;; were used for the same VALue (bug#49866). + ;; So we keep this info in `cl--generic-eql-used'. + (cl-pushnew specializer specializers :test #'equal) + (puthash val `(eql . ,specializers) cl--generic-eql-used)) (list cl--generic-eql-generalizer)) (cl--generic-prefill-dispatchers 0 (eql nil)) diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index b48a48fb944..dd7511e9afe 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -60,7 +60,10 @@ (defvar cl--generic-fooval 41) (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y) "forty-two") - (should (equal (cl--generic-1 42 nil) "forty-two"))) + (cl-defmethod cl--generic-1 (_x (_y (eql 42))) + "FORTY-TWO") + (should (equal (cl--generic-1 42 nil) "forty-two")) + (should (equal (cl--generic-1 nil 42) "FORTY-TWO"))) (cl-defstruct cl-generic-struct-parent a b) (cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c) -- cgit v1.2.3