Merge branch 'lisp-func-type-decls' into 'master'

This commit is contained in:
Andrea Corallo 2024-05-02 17:06:07 +02:00
commit da8b06bd61
14 changed files with 147 additions and 76 deletions

View file

@ -2709,6 +2709,58 @@ native code emitted for the function. In particular, if @var{n} is
@minus{}1, native compilation of the function will emit bytecode @minus{}1, native compilation of the function will emit bytecode
instead of native code for the function. instead of native code for the function.
@item (type @var{type})
Declare @var{type} to be the type of this function. This is used for
documentation by @code{describe-function}. Also it can be used by the
native compiler (@pxref{Native Compilation}) for improving code
generation and for deriving more precisely the type of other functions
without type declaration.
@var{type} is a type specifier in the form @w{@code{(function
(ARG-1-TYPE ... ARG-N-TYPE) RETURN-TYPE)}}. Argument types can be
interleaved with symbols @code{&optional} and @code{&rest} to match the
function's arguments (@pxref{Argument List}).
Here's an example of using @code{type} inside @code{declare} to declare
a function @code{positive-p} that takes an argument of type @var{number}
and return a @var{boolean}:
@group
@lisp
(defun positive-p (x)
(declare (type (function (number) boolean)))
(when (> x 0)
t))
@end lisp
@end group
Similarly this declares a function @code{cons-or-number} that: expects a
first argument being a @var{cons} or a @var{number}, a second optional
argument of type @var{string} and return one of the symbols
@code{is-cons} or @code{is-number}:
@group
@lisp
(defun cons-or-number (x &optional err-msg)
(declare (type (function ((or cons number) &optional string)
(member is-cons is-number))))
(if (consp x)
'is-cons
(if (numberp x)
'is-number
(error (or err-msg "Unexpected input")))))
@end lisp
@end group
More types are described in the Lisp Data Types chapter (@ref{Lisp Data
Types}).
Declaring a function with an incorrect type produces undefined behavior
and could lead to unexpected results or might even crash Emacs when code
is native-compiled and loaded. Note also that when redefining (or
advising) a type declared function the replacement should respect the
original signature to avoid undefined behavior.
@item no-font-lock-keyword @item no-font-lock-keyword
This is valid for macros only. Macros with this declaration are This is valid for macros only. Macros with this declaration are
highlighted by font-lock (@pxref{Font Lock Mode}) as normal functions, highlighted by font-lock (@pxref{Font Lock Mode}) as normal functions,

View file

@ -1939,6 +1939,11 @@ unibyte string.
* Lisp Changes in Emacs 30.1 * Lisp Changes in Emacs 30.1
+++
** Function type declaration
It is now possible, using the 'declare' macro, to declare expected types
of function arguments and return type.
** New types 'closure' and 'interpreted-function'. ** New types 'closure' and 'interpreted-function'.
'interpreted-function' is the new type used for interpreted functions, 'interpreted-function' is the new type used for interpreted functions,
and 'closure' is the common parent type of 'interpreted-function' and 'closure' is the common parent type of 'interpreted-function'

View file

@ -667,7 +667,8 @@ If NOSET is non-nil, don't bother autoloading LOAD when setting the variable."
A customizable variable is either (i) a variable whose property A customizable variable is either (i) a variable whose property
list contains a non-nil `standard-value' or `custom-autoload' list contains a non-nil `standard-value' or `custom-autoload'
property, or (ii) an alias for another customizable variable." property, or (ii) an alias for another customizable variable."
(declare (side-effect-free t)) (declare (type (function (symbol) t))
(side-effect-free t))
(when (symbolp variable) (when (symbolp variable)
(setq variable (indirect-variable variable)) (setq variable (indirect-variable variable))
(or (get variable 'standard-value) (or (get variable 'standard-value)

View file

@ -217,6 +217,11 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
(cadr elem))) (cadr elem)))
val))))) val)))))
(defalias 'byte-run--set-function-type
#'(lambda (f _args &rest val)
(list 'function-put (list 'quote f)
''function-type (list 'quote val))))
;; Add any new entries to info node `(elisp)Declare Form'. ;; Add any new entries to info node `(elisp)Declare Form'.
(defvar defun-declarations-alist (defvar defun-declarations-alist
(list (list
@ -239,7 +244,8 @@ If `error-free', drop calls even if `byte-compile-delete-errors' is nil.")
(list 'speed #'byte-run--set-speed) (list 'speed #'byte-run--set-speed)
(list 'completion #'byte-run--set-completion) (list 'completion #'byte-run--set-completion)
(list 'modes #'byte-run--set-modes) (list 'modes #'byte-run--set-modes)
(list 'interactive-args #'byte-run--set-interactive-args)) (list 'interactive-args #'byte-run--set-interactive-args)
(list 'type #'byte-run--set-function-type))
"List associating function properties to their macro expansion. "List associating function properties to their macro expansion.
Each element of the list takes the form (PROP FUN) where FUN is Each element of the list takes the form (PROP FUN) where FUN is
a function. For each (PROP . VALUES) in a function's declaration, a function. For each (PROP . VALUES) in a function's declaration,

View file

@ -68,7 +68,7 @@ Used to modify the compiler environment."
:risky t :risky t
:version "28.1") :version "28.1")
(defconst comp-known-type-specifiers (defconst comp-primitive-type-specifiers
`( `(
;; Functions we can trust not to be redefined, or, if redefined, ;; Functions we can trust not to be redefined, or, if redefined,
;; to expose the same type. The vast majority of these are ;; to expose the same type. The vast majority of these are
@ -97,7 +97,6 @@ Used to modify the compiler environment."
(assq (function (t list) list)) (assq (function (t list) list))
(atan (function (number &optional number) float)) (atan (function (number &optional number) float))
(atom (function (t) boolean)) (atom (function (t) boolean))
(bignump (function (t) boolean))
(bobp (function () boolean)) (bobp (function () boolean))
(bolp (function () boolean)) (bolp (function () boolean))
(bool-vector-count-consecutive (bool-vector-count-consecutive
@ -107,7 +106,6 @@ Used to modify the compiler environment."
(bool-vector-p (function (t) boolean)) (bool-vector-p (function (t) boolean))
(bool-vector-subsetp (function (bool-vector bool-vector) boolean)) (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
(boundp (function (symbol) boolean)) (boundp (function (symbol) boolean))
(buffer-end (function ((or number marker)) integer))
(buffer-file-name (function (&optional buffer) (or string null))) (buffer-file-name (function (&optional buffer) (or string null)))
(buffer-list (function (&optional frame) list)) (buffer-list (function (&optional frame) list))
(buffer-local-variables (function (&optional buffer) list)) (buffer-local-variables (function (&optional buffer) list))
@ -157,8 +155,6 @@ Used to modify the compiler environment."
(copy-sequence (function (sequence) sequence)) (copy-sequence (function (sequence) sequence))
(copysign (function (float float) float)) (copysign (function (float float) float))
(cos (function (number) float)) (cos (function (number) float))
(count-lines
(function ((or integer marker) (or integer marker) &optional t) integer))
(current-buffer (function () buffer)) (current-buffer (function () buffer))
(current-global-map (function () cons)) (current-global-map (function () cons))
(current-indentation (function () integer)) (current-indentation (function () integer))
@ -171,7 +167,6 @@ Used to modify the compiler environment."
(current-time-zone (function (&optional (or number list) (current-time-zone (function (&optional (or number list)
(or symbol string cons integer)) (or symbol string cons integer))
cons)) cons))
(custom-variable-p (function (symbol) t))
(decode-char (function (cons t) (or fixnum null))) (decode-char (function (cons t) (or fixnum null)))
(decode-time (function (&optional (or number list) (decode-time (function (&optional (or number list)
(or symbol string cons integer) (or symbol string cons integer)
@ -179,7 +174,6 @@ Used to modify the compiler environment."
cons)) cons))
(default-boundp (function (symbol) boolean)) (default-boundp (function (symbol) boolean))
(default-value (function (symbol) t)) (default-value (function (symbol) t))
(degrees-to-radians (function (number) float))
(documentation (documentation
(function ((or function symbol subr) &optional t) (or null string))) (function ((or function symbol subr) &optional t) (or null string)))
(downcase (function ((or fixnum string)) (or fixnum string))) (downcase (function ((or fixnum string)) (or fixnum string)))
@ -192,7 +186,6 @@ Used to modify the compiler environment."
(eql (function (t t) boolean)) (eql (function (t t) boolean))
(equal (function (t t) boolean)) (equal (function (t t) boolean))
(error-message-string (function (list) string)) (error-message-string (function (list) string))
(eventp (function (t) boolean))
(exp (function (number) float)) (exp (function (number) float))
(expt (function (number number) number)) (expt (function (number number) number))
(fboundp (function (symbol) boolean)) (fboundp (function (symbol) boolean))
@ -207,7 +200,6 @@ Used to modify the compiler environment."
(file-readable-p (function (string) boolean)) (file-readable-p (function (string) boolean))
(file-symlink-p (function (string) (or boolean string))) (file-symlink-p (function (string) (or boolean string)))
(file-writable-p (function (string) boolean)) (file-writable-p (function (string) boolean))
(fixnump (function (t) boolean))
(float (function (number) float)) (float (function (number) float))
(float-time (function (&optional (or number list)) float)) (float-time (function (&optional (or number list)) float))
(floatp (function (t) boolean)) (floatp (function (t) boolean))
@ -230,18 +222,12 @@ Used to modify the compiler environment."
(function (&optional (or buffer string) (or symbol (integer 0 0))) (function (&optional (or buffer string) (or symbol (integer 0 0)))
(or null window))) (or null window)))
(get-file-buffer (function (string) (or null buffer))) (get-file-buffer (function (string) (or null buffer)))
(get-largest-window (function (&optional t t t) (or window null)))
(get-lru-window (function (&optional t t t) (or window null)))
(getenv (function (string &optional frame) (or null string)))
(gethash (function (t hash-table &optional t) t)) (gethash (function (t hash-table &optional t) t))
(hash-table-count (function (hash-table) integer)) (hash-table-count (function (hash-table) integer))
(hash-table-p (function (t) boolean)) (hash-table-p (function (t) boolean))
(identity (function (t) t)) (identity (function (t) t))
(ignore (function (&rest t) null))
(int-to-string (function (number) string))
(integer-or-marker-p (function (t) boolean)) (integer-or-marker-p (function (t) boolean))
(integerp (function (t) boolean)) (integerp (function (t) boolean))
(interactive-p (function () boolean))
(intern-soft (function ((or string symbol) &optional (or obarray vector)) (intern-soft (function ((or string symbol) &optional (or obarray vector))
symbol)) symbol))
(invocation-directory (function () string)) (invocation-directory (function () string))
@ -250,8 +236,6 @@ Used to modify the compiler environment."
(keymap-parent (function (cons) (or cons null))) (keymap-parent (function (cons) (or cons null)))
(keymapp (function (t) boolean)) (keymapp (function (t) boolean))
(keywordp (function (t) boolean)) (keywordp (function (t) boolean))
(last (function (list &optional integer) list))
(lax-plist-get (function (list t) t))
(ldexp (function (number integer) float)) (ldexp (function (number integer) float))
(length (function (t) (integer 0 *))) (length (function (t) (integer 0 *)))
(length< (function (sequence fixnum) boolean)) (length< (function (sequence fixnum) boolean))
@ -265,7 +249,6 @@ Used to modify the compiler environment."
(local-variable-p (function (symbol &optional buffer) boolean)) (local-variable-p (function (symbol &optional buffer) boolean))
(locale-info (function ((member codeset days months paper)) (or null string))) (locale-info (function ((member codeset days months paper)) (or null string)))
(log (function (number number) float)) (log (function (number number) float))
(log10 (function (number) float))
(logand (function (&rest (or integer marker)) integer)) (logand (function (&rest (or integer marker)) integer))
(logb (function (number) integer)) (logb (function (number) integer))
(logcount (function (integer) integer)) (logcount (function (integer) integer))
@ -273,7 +256,6 @@ Used to modify the compiler environment."
(lognot (function (integer) integer)) (lognot (function (integer) integer))
(logxor (function (&rest (or integer marker)) integer)) (logxor (function (&rest (or integer marker)) integer))
;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ? ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
(lsh (function (integer integer) integer))
(make-byte-code (make-byte-code
(function ((or fixnum list) string vector integer &optional string t (function ((or fixnum list) string vector integer &optional string t
&rest t) &rest t)
@ -282,14 +264,12 @@ Used to modify the compiler environment."
(make-marker (function () marker)) (make-marker (function () marker))
(make-string (function (integer fixnum &optional t) string)) (make-string (function (integer fixnum &optional t) string))
(make-symbol (function (string) symbol)) (make-symbol (function (string) symbol))
(mark (function (&optional t) (or integer null)))
(mark-marker (function () marker)) (mark-marker (function () marker))
(marker-buffer (function (marker) (or buffer null))) (marker-buffer (function (marker) (or buffer null)))
(markerp (function (t) boolean)) (markerp (function (t) boolean))
(max (function ((or number marker) &rest (or number marker)) number)) (max (function ((or number marker) &rest (or number marker)) number))
(max-char (function (&optional t) fixnum)) (max-char (function (&optional t) fixnum))
(member (function (t list) list)) (member (function (t list) list))
(memory-limit (function () integer))
(memq (function (t list) list)) (memq (function (t list) list))
(memql (function (t list) list)) (memql (function (t list) list))
(min (function ((or number marker) &rest (or number marker)) number)) (min (function ((or number marker) &rest (or number marker)) number))
@ -298,7 +278,6 @@ Used to modify the compiler environment."
(mod (mod
(function ((or number marker) (or number marker)) (function ((or number marker) (or number marker))
(or (integer 0 *) (float 0 *)))) (or (integer 0 *) (float 0 *))))
(mouse-movement-p (function (t) boolean))
(multibyte-char-to-unibyte (function (fixnum) fixnum)) (multibyte-char-to-unibyte (function (fixnum) fixnum))
(natnump (function (t) boolean)) (natnump (function (t) boolean))
(next-window (function (&optional window t t) window)) (next-window (function (&optional window t t) window))
@ -310,9 +289,7 @@ Used to modify the compiler environment."
(number-or-marker-p (function (t) boolean)) (number-or-marker-p (function (t) boolean))
(number-to-string (function (number) string)) (number-to-string (function (number) string))
(numberp (function (t) boolean)) (numberp (function (t) boolean))
(one-window-p (function (&optional t t) boolean))
(overlayp (function (t) boolean)) (overlayp (function (t) boolean))
(parse-colon-path (function (string) list))
(plist-get (function (list t &optional t) t)) (plist-get (function (list t &optional t) t))
(plist-member (function (list t &optional t) list)) (plist-member (function (list t &optional t) list))
(point (function () integer)) (point (function () integer))
@ -325,13 +302,11 @@ Used to modify the compiler environment."
(processp (function (t) boolean)) (processp (function (t) boolean))
(proper-list-p (function (t) (or fixnum null))) (proper-list-p (function (t) (or fixnum null)))
(propertize (function (string &rest t) string)) (propertize (function (string &rest t) string))
(radians-to-degrees (function (number) float))
(rassoc (function (t list) list)) (rassoc (function (t list) list))
(rassq (function (t list) list)) (rassq (function (t list) list))
(read-from-string (function (string &optional integer integer) cons)) (read-from-string (function (string &optional integer integer) cons))
(recent-keys (function (&optional (or cons null)) vector)) (recent-keys (function (&optional (or cons null)) vector))
(recursion-depth (function () integer)) (recursion-depth (function () integer))
(regexp-opt (function (list) string))
(regexp-quote (function (string) string)) (regexp-quote (function (string) string))
(region-beginning (function () integer)) (region-beginning (function () integer))
(region-end (function () integer)) (region-end (function () integer))
@ -387,7 +362,6 @@ Used to modify the compiler environment."
(upcase (function ((or fixnum string)) (or fixnum string))) (upcase (function ((or fixnum string)) (or fixnum string)))
(user-full-name (function (&optional integer) (or string null))) (user-full-name (function (&optional integer) (or string null)))
(user-login-name (function (&optional integer) (or string null))) (user-login-name (function (&optional integer) (or string null)))
(user-original-login-name (function (&optional integer) (or string null)))
(user-real-login-name (function () string)) (user-real-login-name (function () string))
(user-real-uid (function () integer)) (user-real-uid (function () integer))
(user-uid (function () integer)) (user-uid (function () integer))
@ -400,13 +374,8 @@ Used to modify the compiler environment."
(window-live-p (function (t) boolean)) (window-live-p (function (t) boolean))
(window-valid-p (function (t) boolean)) (window-valid-p (function (t) boolean))
(windowp (function (t) boolean)) (windowp (function (t) boolean))
(zerop (function (number) boolean))
;; Type hints
(comp-hint-fixnum (function (t) fixnum))
(comp-hint-cons (function (t) cons))
;; Non returning functions ;; Non returning functions
(throw (function (t t) nil)) (throw (function (t t) nil))
(error (function (string &rest t) nil))
(signal (function (symbol t) nil))) (signal (function (symbol t) nil)))
"Alist used for type propagation.") "Alist used for type propagation.")
@ -532,22 +501,27 @@ Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
(defun comp-function-type-spec (function) (defun comp-function-type-spec (function)
"Return the type specifier of FUNCTION. "Return the type specifier of FUNCTION.
This function returns a cons cell whose car is the function This function returns a cons cell whose car is the function specifier,
specifier, and cdr is a symbol, either `inferred' or `know'. and cdr is a symbol, either `inferred' or `declared'. If the symbol is
If the symbol is `inferred', the type specifier is automatically `inferred', the type specifier is automatically inferred from the code
inferred from the code itself by the native compiler; if it is itself by the native compiler; if it is `declared', the type specifier
`know', the type specifier comes from `comp-known-type-specifiers'." comes from `comp-primitive-type-specifiers' or the function type declaration
(let ((kind 'know) itself."
type-spec ) (let ((kind 'declared)
(when-let ((res (assoc function comp-known-type-specifiers))) type-spec)
(when-let ((res (assoc function comp-primitive-type-specifiers)))
;; Declared primitive
(setf type-spec (cadr res))) (setf type-spec (cadr res)))
(let ((f (and (symbolp function) (let ((f (and (symbolp function)
(symbol-function function)))) (symbol-function function))))
(when (and f (when (and f (null type-spec))
(null type-spec) (if-let ((delc-type (function-get function 'function-type)))
(subr-native-elisp-p f)) ;; Declared Lisp function
(setf kind 'inferred (setf type-spec (car delc-type))
type-spec (subr-type f)))) (when (subr-native-elisp-p f)
;; Native compiled inferred
(setf kind 'inferred
type-spec (subr-type f))))))
(when type-spec (when type-spec
(cons type-spec kind)))) (cons type-spec kind))))

View file

@ -179,16 +179,24 @@ For internal use by the test suite only.")
Each function in FUNCTIONS is run after PASS. Each function in FUNCTIONS is run after PASS.
Useful to hook into pass checkers.") Useful to hook into pass checkers.")
(defconst comp-known-func-cstr-h (defconst comp-primitive-func-cstr-h
(cl-loop (cl-loop
with comp-ctxt = (make-comp-cstr-ctxt) with comp-ctxt = (make-comp-cstr-ctxt)
with h = (make-hash-table :test #'eq) with h = (make-hash-table :test #'eq)
for (f type-spec) in comp-known-type-specifiers for (f type-spec) in comp-primitive-type-specifiers
for cstr = (comp-type-spec-to-cstr type-spec) for cstr = (comp-type-spec-to-cstr type-spec)
do (puthash f cstr h) do (puthash f cstr h)
finally return h) finally return h)
"Hash table function -> `comp-constraint'.") "Hash table function -> `comp-constraint'.")
(defun comp--get-function-cstr (function)
"Given FUNCTION return the corresponding `comp-constraint'."
(when (symbolp function)
(let ((f (symbol-function function)))
(or (gethash f comp-primitive-func-cstr-h)
(when-let ((res (function-get function 'function-type)))
(comp-type-spec-to-cstr (car res)))))))
;; Keep it in sync with the `cl-deftype-satisfies' property set in ;; Keep it in sync with the `cl-deftype-satisfies' property set in
;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the ;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the
;; relation type <-> predicate is not bijective (bug#45576). ;; relation type <-> predicate is not bijective (bug#45576).
@ -2102,10 +2110,10 @@ TARGET-BB-SYM is the symbol name of the target block."
(when-let ((match (when-let ((match
(pcase insn (pcase insn
(`(set ,lhs (,(pred comp--call-op-p) ,f . ,args)) (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args))
(when-let ((cstr-f (gethash f comp-known-func-cstr-h))) (when-let ((cstr-f (comp--get-function-cstr f)))
(cl-values f cstr-f lhs args))) (cl-values f cstr-f lhs args)))
(`(,(pred comp--call-op-p) ,f . ,args) (`(,(pred comp--call-op-p) ,f . ,args)
(when-let ((cstr-f (gethash f comp-known-func-cstr-h))) (when-let ((cstr-f (comp--get-function-cstr f)))
(cl-values f cstr-f nil args)))))) (cl-values f cstr-f nil args))))))
(cl-multiple-value-bind (f cstr-f lhs args) match (cl-multiple-value-bind (f cstr-f lhs args) match
(cl-loop (cl-loop
@ -2642,7 +2650,7 @@ Fold the call in case."
(comp-cstr-imm-vld-p (car args))) (comp-cstr-imm-vld-p (car args)))
(setf f (comp-cstr-imm (car args)) (setf f (comp-cstr-imm (car args))
args (cdr args))) args (cdr args)))
(when-let ((cstr-f (gethash f comp-known-func-cstr-h))) (when-let ((cstr-f (comp--get-function-cstr f)))
(let ((cstr (comp-cstr-f-ret cstr-f))) (let ((cstr (comp-cstr-f-ret cstr-f)))
(when (comp-cstr-empty-p cstr) (when (comp-cstr-empty-p cstr)
;; Store it to be rewritten as non local exit. ;; Store it to be rewritten as non local exit.
@ -3301,11 +3309,13 @@ Prepare every function for final compilation and drive the C back-end."
;; are assumed just to be true. Use with extreme caution... ;; are assumed just to be true. Use with extreme caution...
(defun comp-hint-fixnum (x) (defun comp-hint-fixnum (x)
(declare (gv-setter (lambda (val) `(setf ,x ,val)))) (declare (type (function (t) fixnum))
(gv-setter (lambda (val) `(setf ,x ,val))))
x) x)
(defun comp-hint-cons (x) (defun comp-hint-cons (x)
(declare (gv-setter (lambda (val) `(setf ,x ,val)))) (declare (type (function (t) cons))
(gv-setter (lambda (val) `(setf ,x ,val))))
x) x)

View file

@ -534,7 +534,8 @@ major mode's decisions about context.")
"Return the \"far end\" position of the buffer, in direction ARG. "Return the \"far end\" position of the buffer, in direction ARG.
If ARG is positive, that's the end of the buffer. If ARG is positive, that's the end of the buffer.
Otherwise, that's the beginning of the buffer." Otherwise, that's the beginning of the buffer."
(declare (side-effect-free error-free)) (declare (type (function ((or number marker)) integer))
(side-effect-free error-free))
(if (> arg 0) (point-max) (point-min))) (if (> arg 0) (point-max) (point-min)))
(defun end-of-defun (&optional arg interactive) (defun end-of-defun (&optional arg interactive)

View file

@ -130,7 +130,8 @@ usually more efficient than that of a simplified version:
(concat (car parens) (concat (car parens)
(mapconcat \\='regexp-quote strings \"\\\\|\") (mapconcat \\='regexp-quote strings \"\\\\|\")
(cdr parens))))" (cdr parens))))"
(declare (pure t) (side-effect-free t)) (declare (type (function (list &optional t) string))
(pure t) (side-effect-free t))
(save-match-data (save-match-data
;; Recurse on the sorted list. ;; Recurse on the sorted list.
(let* ((max-lisp-eval-depth 10000) (let* ((max-lisp-eval-depth 10000)

View file

@ -207,7 +207,8 @@ parameter.
Otherwise, this function searches `process-environment' for Otherwise, this function searches `process-environment' for
VARIABLE. If it is not found there, then it continues the search VARIABLE. If it is not found there, then it continues the search
in the environment list of the selected frame." in the environment list of the selected frame."
(declare (side-effect-free t)) (declare (type (function (string &optional frame) (or null string)))
(side-effect-free t))
(interactive (list (read-envvar-name "Get environment variable: " t))) (interactive (list (read-envvar-name "Get environment variable: " t)))
(let ((value (getenv-internal (if (multibyte-string-p variable) (let ((value (getenv-internal (if (multibyte-string-p variable)
(encode-coding-string (encode-coding-string

View file

@ -862,6 +862,7 @@ GNU and Unix systems). Substitute environment variables into the
resulting list of directory names. For an empty path element (i.e., resulting list of directory names. For an empty path element (i.e.,
a leading or trailing separator, or two adjacent separators), return a leading or trailing separator, or two adjacent separators), return
nil (meaning `default-directory') as the associated list element." nil (meaning `default-directory') as the associated list element."
(declare (type (function (string) list)))
(when (stringp search-path) (when (stringp search-path)
(let ((spath (substitute-env-vars search-path)) (let ((spath (substitute-env-vars search-path))
(double-slash-special-p (double-slash-special-p

View file

@ -732,7 +732,7 @@ the C sources, too."
(insert (format (insert (format
(if (eq kind 'inferred) (if (eq kind 'inferred)
"\nInferred type: %s\n" "\nInferred type: %s\n"
"\nType: %s\n") "\nDeclared type: %s\n")
type-spec)))) type-spec))))
(fill-region fill-begin (point)) (fill-region fill-begin (point))
high-doc))))) high-doc)))))

View file

@ -1762,7 +1762,9 @@ not at the start of a line.
When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not
included in the count." included in the count."
(declare (side-effect-free t)) (declare (type (function ((or integer marker) (or integer marker) &optional t)
integer))
(side-effect-free t))
(save-excursion (save-excursion
(save-restriction (save-restriction
(narrow-to-region start end) (narrow-to-region start end)
@ -6882,7 +6884,8 @@ is active, and returns an integer or nil in the usual way.
If you are using this in an editing command, you are most likely making If you are using this in an editing command, you are most likely making
a mistake; see the documentation of `set-mark'." a mistake; see the documentation of `set-mark'."
(declare (side-effect-free t)) (declare (type (function (&optional t) (or integer null)))
(side-effect-free t))
(if (or force (not transient-mark-mode) mark-active mark-even-if-inactive) (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
(marker-position (mark-marker)) (marker-position (mark-marker))
(signal 'mark-inactive nil))) (signal 'mark-inactive nil)))
@ -11163,7 +11166,8 @@ killed."
(defun lax-plist-get (plist prop) (defun lax-plist-get (plist prop)
"Extract a value from a property list, comparing with `equal'." "Extract a value from a property list, comparing with `equal'."
(declare (pure t) (side-effect-free t) (obsolete plist-get "29.1")) (declare (type (function (list t) t))
(pure t) (side-effect-free t) (obsolete plist-get "29.1"))
(plist-get plist prop #'equal)) (plist-get plist prop #'equal))
(defun lax-plist-put (plist prop val) (defun lax-plist-put (plist prop val)

View file

@ -451,7 +451,8 @@ This function accepts any number of arguments in ARGUMENTS.
Also see `always'." Also see `always'."
;; Not declared `side-effect-free' because we don't want calls to it ;; Not declared `side-effect-free' because we don't want calls to it
;; elided; see `byte-compile-ignore'. ;; elided; see `byte-compile-ignore'.
(declare (pure t) (completion ignore)) (declare (type (function (&rest t) null))
(pure t) (completion ignore))
(interactive) (interactive)
nil) nil)
@ -480,7 +481,8 @@ for the sake of consistency.
To alter the look of the displayed error messages, you can use To alter the look of the displayed error messages, you can use
the `command-error-function' variable." the `command-error-function' variable."
(declare (advertised-calling-convention (string &rest args) "23.1")) (declare (type (function (string &rest t) nil))
(advertised-calling-convention (string &rest args) "23.1"))
(signal 'error (list (apply #'format-message args)))) (signal 'error (list (apply #'format-message args))))
(defun user-error (format &rest args) (defun user-error (format &rest args)
@ -545,19 +547,22 @@ was called."
"Return t if NUMBER is zero." "Return t if NUMBER is zero."
;; Used to be in C, but it's pointless since (= 0 n) is faster anyway because ;; Used to be in C, but it's pointless since (= 0 n) is faster anyway because
;; = has a byte-code. ;; = has a byte-code.
(declare (pure t) (side-effect-free t) (declare (type (function (number) boolean))
(pure t) (side-effect-free t)
(compiler-macro (lambda (_) `(= 0 ,number)))) (compiler-macro (lambda (_) `(= 0 ,number))))
(= 0 number)) (= 0 number))
(defun fixnump (object) (defun fixnump (object)
"Return t if OBJECT is a fixnum." "Return t if OBJECT is a fixnum."
(declare (side-effect-free error-free)) (declare (type (function (t) boolean))
(side-effect-free error-free))
(and (integerp object) (and (integerp object)
(<= most-negative-fixnum object most-positive-fixnum))) (<= most-negative-fixnum object most-positive-fixnum)))
(defun bignump (object) (defun bignump (object)
"Return t if OBJECT is a bignum." "Return t if OBJECT is a bignum."
(declare (side-effect-free error-free)) (declare (type (function (t) boolean))
(side-effect-free error-free))
(and (integerp object) (not (fixnump object)))) (and (integerp object) (not (fixnump object))))
(defun lsh (value count) (defun lsh (value count)
@ -570,7 +575,8 @@ Most uses of this function turn out to be mistakes. We recommend
to use `ash' instead, unless COUNT could ever be negative, and to use `ash' instead, unless COUNT could ever be negative, and
if, when COUNT is negative, your program really needs the special if, when COUNT is negative, your program really needs the special
treatment of negative COUNT provided by this function." treatment of negative COUNT provided by this function."
(declare (compiler-macro (declare (type (function (integer integer) integer))
(compiler-macro
(lambda (form) (lambda (form)
(macroexp-warn-and-return (macroexp-warn-and-return
(format-message "avoid `lsh'; use `ash' instead") (format-message "avoid `lsh'; use `ash' instead")
@ -748,7 +754,8 @@ treatment of negative COUNT provided by this function."
If LIST is nil, return nil. If LIST is nil, return nil.
If N is non-nil, return the Nth-to-last link of LIST. If N is non-nil, return the Nth-to-last link of LIST.
If N is bigger than the length of LIST, return LIST." If N is bigger than the length of LIST, return LIST."
(declare (pure t) (side-effect-free t)) ; pure up to mutation (declare (type (function (list &optional integer) list))
(pure t) (side-effect-free t)) ; pure up to mutation
(if n (if n
(and (>= n 0) (and (>= n 0)
(let ((m (safe-length list))) (let ((m (safe-length list)))
@ -1585,7 +1592,8 @@ See also `current-global-map'.")
(defun eventp (object) (defun eventp (object)
"Return non-nil if OBJECT is an input event or event object." "Return non-nil if OBJECT is an input event or event object."
(declare (pure t) (side-effect-free error-free)) (declare (type (function (t) boolean))
(pure t) (side-effect-free error-free))
(or (integerp object) (or (integerp object)
(and (if (consp object) (and (if (consp object)
(setq object (car object)) (setq object (car object))
@ -1652,7 +1660,8 @@ in the current Emacs session, then this function may return nil."
(defsubst mouse-movement-p (object) (defsubst mouse-movement-p (object)
"Return non-nil if OBJECT is a mouse movement event." "Return non-nil if OBJECT is a mouse movement event."
(declare (side-effect-free error-free)) (declare (type (function (t) boolean))
(side-effect-free error-free))
(eq (car-safe object) 'mouse-movement)) (eq (car-safe object) 'mouse-movement))
(defun mouse-event-p (object) (defun mouse-event-p (object)
@ -1961,7 +1970,8 @@ be a list of the form returned by `event-start' and `event-end'."
(defun log10 (x) (defun log10 (x)
"Return (log X 10), the log base 10 of X." "Return (log X 10), the log base 10 of X."
(declare (side-effect-free t) (obsolete log "24.4")) (declare (type (function (number) float))
(side-effect-free t) (obsolete log "24.4"))
(log x 10)) (log x 10))
(set-advertised-calling-convention (set-advertised-calling-convention
@ -3245,7 +3255,8 @@ It can be retrieved with `(process-get PROCESS PROPNAME)'."
(defun memory-limit () (defun memory-limit ()
"Return an estimate of Emacs virtual memory usage, divided by 1024." "Return an estimate of Emacs virtual memory usage, divided by 1024."
(declare (side-effect-free error-free)) (declare (type (function () integer))
(side-effect-free error-free))
(let ((default-directory temporary-file-directory)) (let ((default-directory temporary-file-directory))
(or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0))) (or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0)))
@ -6467,7 +6478,8 @@ To test whether a function can be called interactively, use
`commandp'." `commandp'."
;; Kept around for now. See discussion at: ;; Kept around for now. See discussion at:
;; https://lists.gnu.org/r/emacs-devel/2020-08/msg00564.html ;; https://lists.gnu.org/r/emacs-devel/2020-08/msg00564.html
(declare (obsolete called-interactively-p "23.2") (declare (type (function () boolean))
(obsolete called-interactively-p "23.2")
(side-effect-free error-free)) (side-effect-free error-free))
(called-interactively-p 'interactive)) (called-interactively-p 'interactive))

View file

@ -2515,7 +2515,8 @@ have special meanings:
Any other value of ALL-FRAMES means consider all windows on the Any other value of ALL-FRAMES means consider all windows on the
selected frame and no others." selected frame and no others."
(declare (side-effect-free error-free)) (declare (type (function (&optional t t t) (or window null)))
(side-effect-free error-free))
(let ((windows (window-list-1 nil 'nomini all-frames)) (let ((windows (window-list-1 nil 'nomini all-frames))
best-window best-time second-best-window second-best-time time) best-window best-time second-best-window second-best-time time)
(dolist (window windows) (dolist (window windows)
@ -2594,7 +2595,8 @@ have special meanings:
Any other value of ALL-FRAMES means consider all windows on the Any other value of ALL-FRAMES means consider all windows on the
selected frame and no others." selected frame and no others."
(declare (side-effect-free error-free)) (declare (type (function (&optional t t t) (or window null)))
(side-effect-free error-free))
(let ((best-size 0) (let ((best-size 0)
best-window size) best-window size)
(dolist (window (window-list-1 nil 'nomini all-frames)) (dolist (window (window-list-1 nil 'nomini all-frames))
@ -4089,7 +4091,8 @@ with a special meaning are:
Anything else means consider all windows on the selected frame Anything else means consider all windows on the selected frame
and no others." and no others."
(declare (side-effect-free error-free)) (declare (type (function (&optional t t) boolean))
(side-effect-free error-free))
(let ((base-window (selected-window))) (let ((base-window (selected-window)))
(if (and nomini (eq base-window (minibuffer-window))) (if (and nomini (eq base-window (minibuffer-window)))
(setq base-window (next-window base-window))) (setq base-window (next-window base-window)))