From 1e47f7492afbca15f5d1f3a76d797443b6553eb4 Mon Sep 17 00:00:00 2001 From: David Ponce Date: Fri, 31 Oct 2025 13:34:46 -0400 Subject: [PATCH] lisp/emacs-lisp/cl-*.el: Minor changes accumulated during new API design * lisp/emacs-lisp/cl-macs.el (cl-deftype): Support dispatch on types that take arguments, as long as they can be used without arguments. * lisp/emacs-lisp/cl-generic.el (cl--generic-derived-mode-specializers): Rename from `cl--generic-derived-specializers` to clarify it's about derived modes and not derived types. (cl--generic-derived-mode-generalizer): Adjust accordingly and rename from `cl--generic-derived-generalizer` for the same reason. Ignore additional args in the tagcode function. (cl-generic-generalizers) : Adjust accordingly. * lisp/emacs-lisp/macroexp.el (macroexp--dynamic-variable-p): Simplify. --- lisp/emacs-lisp/cl-generic.el | 12 ++++++------ lisp/emacs-lisp/cl-macs.el | 37 ++++++++++++++++++++++++++++++----- lisp/emacs-lisp/macroexp.el | 1 - 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 453a49e6609..ad032e82e9e 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1047,7 +1047,7 @@ those methods.") ('cl--generic-eql-generalizer '(eql 'x)) ('cl--generic-struct-generalizer 'cl--generic) ('cl--generic-typeof-generalizer 'integer) - ('cl--generic-derived-generalizer '(derived-mode c-mode)) + ('cl--generic-derived-mode-generalizer '(derived-mode c-mode)) ('cl--generic-oclosure-generalizer 'oclosure) (_ x)))) @@ -1466,19 +1466,19 @@ This currently works for built-in types and types built on top of records." ;; "&context (major-mode c-mode)" rather than ;; "&context (major-mode (derived-mode c-mode))". -(defun cl--generic-derived-specializers (mode &rest _) +(defun cl--generic-derived-mode-specializers (mode &rest _) ;; FIXME: Handle (derived-mode ... ) (mapcar (lambda (mode) `(derived-mode ,mode)) (derived-mode-all-parents mode))) -(cl-generic-define-generalizer cl--generic-derived-generalizer - 90 (lambda (name) `(and (symbolp ,name) (functionp ,name) ,name)) - #'cl--generic-derived-specializers) +(cl-generic-define-generalizer cl--generic-derived-mode-generalizer + 90 (lambda (name &rest _) `(and (symbolp ,name) (functionp ,name) ,name)) + #'cl--generic-derived-mode-specializers) (cl-defmethod cl-generic-generalizers ((_specializer (head derived-mode))) "Support for (derived-mode MODE) specializers. Used internally for the (major-mode MODE) context specializers." - (list cl--generic-derived-generalizer)) + (list cl--generic-derived-mode-generalizer)) (cl-generic-define-context-rewriter major-mode (mode &rest modes) `(major-mode ,(if (consp mode) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 2c2451e14cd..73b3b243643 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3816,12 +3816,39 @@ If PARENTS is non-nil, ARGLIST must be nil." (cl-callf (lambda (x) (delq parent-decl x)) (cdr declares)) (when (equal declares '(declare)) (cl-callf (lambda (x) (delq declares x)) decls))) - (and parents arglist - (error "Parents specified, but arglist not empty")) (let* ((expander - `(cl-function (lambda (&cl-defs ('*) ,@arglist) ,@decls ,@forms))) - ;; FIXME: Pass a better lexical context. - (specifier (ignore-errors (funcall (eval expander t)))) + `(cl-function + (lambda (&cl-defs ('*) ,@arglist) ,@decls ,@forms))) + (specifier + (condition-case nil + ;; FIXME: Pass a better lexical context. + (funcall (eval expander t)) + ;; We previously signaled an error when the type specified + ;; both non-nil parents and arglist, like `unsigned-byte' + ;; in below example: + ;; + ;; (cl-deftype my-integer () + ;; 'integer) + ;; + ;; (cl-deftype unsigned-byte (&optional bits) + ;; "Unsigned integer." + ;; (declare (parents my-integer)) + ;; `(integer 0 ,(if (memq bits '(nil *)) + ;; bits + ;; (1- (ash 1 bits))))) + ;; + ;; In order to accept the above (correct) definition of + ;; `unsigned-byte', call the expander without arguments to + ;; check if the arglist is mandatory by catching a + ;; `wrong-number-of-arguments' error. If so, and the type + ;; specified both parents and arglist, there is a good + ;; chance that the type is not atomic, so signal it; + ;; otherwise, return nil as previously. Report any other + ;; error on type definition. + (wrong-number-of-arguments + (and parents arglist ;; type is not atomic + (error "Type %S with parents may be not atomic: %S" + name arglist))))) (predicate (pcase specifier (`(satisfies ,f) `#',f) diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 2bf9e0eb451..e89ad4e17e4 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -399,7 +399,6 @@ change this." (defun macroexp--dynamic-variable-p (var) "Whether the variable VAR is dynamically scoped. Only valid during macro-expansion." - (defvar byte-compile-bound-variables) (or (not lexical-binding) (special-variable-p var) (memq var macroexp--dynvars)