aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Corallo2024-05-02 17:06:07 +0200
committerAndrea Corallo2024-05-02 17:06:07 +0200
commitda8b06bd6181bc56fb0f133d17cae7eff44a83e8 (patch)
treed688dd259d446c49795d4728180faf989ab77a30
parent2f5c9b31161306b2b4c46c77c351c6ea6a46ff98 (diff)
parent64d3100cb5973f2e8372d29f7658c32a63e191e2 (diff)
downloademacs-da8b06bd6181bc56fb0f133d17cae7eff44a83e8.tar.gz
emacs-da8b06bd6181bc56fb0f133d17cae7eff44a83e8.zip
Merge branch 'lisp-func-type-decls' into 'master'
-rw-r--r--doc/lispref/functions.texi52
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/custom.el3
-rw-r--r--lisp/emacs-lisp/byte-run.el8
-rw-r--r--lisp/emacs-lisp/comp-common.el64
-rw-r--r--lisp/emacs-lisp/comp.el24
-rw-r--r--lisp/emacs-lisp/lisp.el3
-rw-r--r--lisp/emacs-lisp/regexp-opt.el3
-rw-r--r--lisp/env.el3
-rw-r--r--lisp/files.el1
-rw-r--r--lisp/help-fns.el2
-rw-r--r--lisp/simple.el10
-rw-r--r--lisp/subr.el36
-rw-r--r--lisp/window.el9
14 files changed, 147 insertions, 76 deletions
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index c57de08460f..d88f5d05339 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -2709,6 +2709,58 @@ native code emitted for the function. In particular, if @var{n} is
2709@minus{}1, native compilation of the function will emit bytecode 2709@minus{}1, native compilation of the function will emit bytecode
2710instead of native code for the function. 2710instead of native code for the function.
2711 2711
2712@item (type @var{type})
2713Declare @var{type} to be the type of this function. This is used for
2714documentation by @code{describe-function}. Also it can be used by the
2715native compiler (@pxref{Native Compilation}) for improving code
2716generation and for deriving more precisely the type of other functions
2717without type declaration.
2718
2719@var{type} is a type specifier in the form @w{@code{(function
2720(ARG-1-TYPE ... ARG-N-TYPE) RETURN-TYPE)}}. Argument types can be
2721interleaved with symbols @code{&optional} and @code{&rest} to match the
2722function's arguments (@pxref{Argument List}).
2723
2724Here's an example of using @code{type} inside @code{declare} to declare
2725a function @code{positive-p} that takes an argument of type @var{number}
2726and return a @var{boolean}:
2727
2728@group
2729@lisp
2730(defun positive-p (x)
2731 (declare (type (function (number) boolean)))
2732 (when (> x 0)
2733 t))
2734@end lisp
2735@end group
2736
2737Similarly this declares a function @code{cons-or-number} that: expects a
2738first argument being a @var{cons} or a @var{number}, a second optional
2739argument of type @var{string} and return one of the symbols
2740@code{is-cons} or @code{is-number}:
2741
2742@group
2743@lisp
2744(defun cons-or-number (x &optional err-msg)
2745 (declare (type (function ((or cons number) &optional string)
2746 (member is-cons is-number))))
2747 (if (consp x)
2748 'is-cons
2749 (if (numberp x)
2750 'is-number
2751 (error (or err-msg "Unexpected input")))))
2752@end lisp
2753@end group
2754
2755More types are described in the Lisp Data Types chapter (@ref{Lisp Data
2756Types}).
2757
2758Declaring a function with an incorrect type produces undefined behavior
2759and could lead to unexpected results or might even crash Emacs when code
2760is native-compiled and loaded. Note also that when redefining (or
2761advising) a type declared function the replacement should respect the
2762original signature to avoid undefined behavior.
2763
2712@item no-font-lock-keyword 2764@item no-font-lock-keyword
2713This is valid for macros only. Macros with this declaration are 2765This is valid for macros only. Macros with this declaration are
2714highlighted by font-lock (@pxref{Font Lock Mode}) as normal functions, 2766highlighted by font-lock (@pxref{Font Lock Mode}) as normal functions,
diff --git a/etc/NEWS b/etc/NEWS
index 4d363d300a8..8477a1eed58 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1939,6 +1939,11 @@ unibyte string.
1939 1939
1940* Lisp Changes in Emacs 30.1 1940* Lisp Changes in Emacs 30.1
1941 1941
1942+++
1943** Function type declaration
1944It is now possible, using the 'declare' macro, to declare expected types
1945of function arguments and return type.
1946
1942** New types 'closure' and 'interpreted-function'. 1947** New types 'closure' and 'interpreted-function'.
1943'interpreted-function' is the new type used for interpreted functions, 1948'interpreted-function' is the new type used for interpreted functions,
1944and 'closure' is the common parent type of 'interpreted-function' 1949and 'closure' is the common parent type of 'interpreted-function'
diff --git a/lisp/custom.el b/lisp/custom.el
index a19b14aaf8a..6f2aa18ba1d 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -667,7 +667,8 @@ If NOSET is non-nil, don't bother autoloading LOAD when setting the variable."
667A customizable variable is either (i) a variable whose property 667A customizable variable is either (i) a variable whose property
668list contains a non-nil `standard-value' or `custom-autoload' 668list contains a non-nil `standard-value' or `custom-autoload'
669property, or (ii) an alias for another customizable variable." 669property, or (ii) an alias for another customizable variable."
670 (declare (side-effect-free t)) 670 (declare (type (function (symbol) t))
671 (side-effect-free t))
671 (when (symbolp variable) 672 (when (symbolp variable)
672 (setq variable (indirect-variable variable)) 673 (setq variable (indirect-variable variable))
673 (or (get variable 'standard-value) 674 (or (get variable 'standard-value)
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index cc176821026..84cc83f2270 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -217,6 +217,11 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
217 (cadr elem))) 217 (cadr elem)))
218 val))))) 218 val)))))
219 219
220(defalias 'byte-run--set-function-type
221 #'(lambda (f _args &rest val)
222 (list 'function-put (list 'quote f)
223 ''function-type (list 'quote val))))
224
220;; Add any new entries to info node `(elisp)Declare Form'. 225;; Add any new entries to info node `(elisp)Declare Form'.
221(defvar defun-declarations-alist 226(defvar defun-declarations-alist
222 (list 227 (list
@@ -239,7 +244,8 @@ If `error-free', drop calls even if `byte-compile-delete-errors' is nil.")
239 (list 'speed #'byte-run--set-speed) 244 (list 'speed #'byte-run--set-speed)
240 (list 'completion #'byte-run--set-completion) 245 (list 'completion #'byte-run--set-completion)
241 (list 'modes #'byte-run--set-modes) 246 (list 'modes #'byte-run--set-modes)
242 (list 'interactive-args #'byte-run--set-interactive-args)) 247 (list 'interactive-args #'byte-run--set-interactive-args)
248 (list 'type #'byte-run--set-function-type))
243 "List associating function properties to their macro expansion. 249 "List associating function properties to their macro expansion.
244Each element of the list takes the form (PROP FUN) where FUN is 250Each element of the list takes the form (PROP FUN) where FUN is
245a function. For each (PROP . VALUES) in a function's declaration, 251a function. For each (PROP . VALUES) in a function's declaration,
diff --git a/lisp/emacs-lisp/comp-common.el b/lisp/emacs-lisp/comp-common.el
index 62fd28f772e..ef40882a98a 100644
--- a/lisp/emacs-lisp/comp-common.el
+++ b/lisp/emacs-lisp/comp-common.el
@@ -68,7 +68,7 @@ Used to modify the compiler environment."
68 :risky t 68 :risky t
69 :version "28.1") 69 :version "28.1")
70 70
71(defconst comp-known-type-specifiers 71(defconst comp-primitive-type-specifiers
72 `( 72 `(
73 ;; Functions we can trust not to be redefined, or, if redefined, 73 ;; Functions we can trust not to be redefined, or, if redefined,
74 ;; to expose the same type. The vast majority of these are 74 ;; to expose the same type. The vast majority of these are
@@ -97,7 +97,6 @@ Used to modify the compiler environment."
97 (assq (function (t list) list)) 97 (assq (function (t list) list))
98 (atan (function (number &optional number) float)) 98 (atan (function (number &optional number) float))
99 (atom (function (t) boolean)) 99 (atom (function (t) boolean))
100 (bignump (function (t) boolean))
101 (bobp (function () boolean)) 100 (bobp (function () boolean))
102 (bolp (function () boolean)) 101 (bolp (function () boolean))
103 (bool-vector-count-consecutive 102 (bool-vector-count-consecutive
@@ -107,7 +106,6 @@ Used to modify the compiler environment."
107 (bool-vector-p (function (t) boolean)) 106 (bool-vector-p (function (t) boolean))
108 (bool-vector-subsetp (function (bool-vector bool-vector) boolean)) 107 (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
109 (boundp (function (symbol) boolean)) 108 (boundp (function (symbol) boolean))
110 (buffer-end (function ((or number marker)) integer))
111 (buffer-file-name (function (&optional buffer) (or string null))) 109 (buffer-file-name (function (&optional buffer) (or string null)))
112 (buffer-list (function (&optional frame) list)) 110 (buffer-list (function (&optional frame) list))
113 (buffer-local-variables (function (&optional buffer) list)) 111 (buffer-local-variables (function (&optional buffer) list))
@@ -157,8 +155,6 @@ Used to modify the compiler environment."
157 (copy-sequence (function (sequence) sequence)) 155 (copy-sequence (function (sequence) sequence))
158 (copysign (function (float float) float)) 156 (copysign (function (float float) float))
159 (cos (function (number) float)) 157 (cos (function (number) float))
160 (count-lines
161 (function ((or integer marker) (or integer marker) &optional t) integer))
162 (current-buffer (function () buffer)) 158 (current-buffer (function () buffer))
163 (current-global-map (function () cons)) 159 (current-global-map (function () cons))
164 (current-indentation (function () integer)) 160 (current-indentation (function () integer))
@@ -171,7 +167,6 @@ Used to modify the compiler environment."
171 (current-time-zone (function (&optional (or number list) 167 (current-time-zone (function (&optional (or number list)
172 (or symbol string cons integer)) 168 (or symbol string cons integer))
173 cons)) 169 cons))
174 (custom-variable-p (function (symbol) t))
175 (decode-char (function (cons t) (or fixnum null))) 170 (decode-char (function (cons t) (or fixnum null)))
176 (decode-time (function (&optional (or number list) 171 (decode-time (function (&optional (or number list)
177 (or symbol string cons integer) 172 (or symbol string cons integer)
@@ -179,7 +174,6 @@ Used to modify the compiler environment."
179 cons)) 174 cons))
180 (default-boundp (function (symbol) boolean)) 175 (default-boundp (function (symbol) boolean))
181 (default-value (function (symbol) t)) 176 (default-value (function (symbol) t))
182 (degrees-to-radians (function (number) float))
183 (documentation 177 (documentation
184 (function ((or function symbol subr) &optional t) (or null string))) 178 (function ((or function symbol subr) &optional t) (or null string)))
185 (downcase (function ((or fixnum string)) (or fixnum string))) 179 (downcase (function ((or fixnum string)) (or fixnum string)))
@@ -192,7 +186,6 @@ Used to modify the compiler environment."
192 (eql (function (t t) boolean)) 186 (eql (function (t t) boolean))
193 (equal (function (t t) boolean)) 187 (equal (function (t t) boolean))
194 (error-message-string (function (list) string)) 188 (error-message-string (function (list) string))
195 (eventp (function (t) boolean))
196 (exp (function (number) float)) 189 (exp (function (number) float))
197 (expt (function (number number) number)) 190 (expt (function (number number) number))
198 (fboundp (function (symbol) boolean)) 191 (fboundp (function (symbol) boolean))
@@ -207,7 +200,6 @@ Used to modify the compiler environment."
207 (file-readable-p (function (string) boolean)) 200 (file-readable-p (function (string) boolean))
208 (file-symlink-p (function (string) (or boolean string))) 201 (file-symlink-p (function (string) (or boolean string)))
209 (file-writable-p (function (string) boolean)) 202 (file-writable-p (function (string) boolean))
210 (fixnump (function (t) boolean))
211 (float (function (number) float)) 203 (float (function (number) float))
212 (float-time (function (&optional (or number list)) float)) 204 (float-time (function (&optional (or number list)) float))
213 (floatp (function (t) boolean)) 205 (floatp (function (t) boolean))
@@ -230,18 +222,12 @@ Used to modify the compiler environment."
230 (function (&optional (or buffer string) (or symbol (integer 0 0))) 222 (function (&optional (or buffer string) (or symbol (integer 0 0)))
231 (or null window))) 223 (or null window)))
232 (get-file-buffer (function (string) (or null buffer))) 224 (get-file-buffer (function (string) (or null buffer)))
233 (get-largest-window (function (&optional t t t) (or window null)))
234 (get-lru-window (function (&optional t t t) (or window null)))
235 (getenv (function (string &optional frame) (or null string)))
236 (gethash (function (t hash-table &optional t) t)) 225 (gethash (function (t hash-table &optional t) t))
237 (hash-table-count (function (hash-table) integer)) 226 (hash-table-count (function (hash-table) integer))
238 (hash-table-p (function (t) boolean)) 227 (hash-table-p (function (t) boolean))
239 (identity (function (t) t)) 228 (identity (function (t) t))
240 (ignore (function (&rest t) null))
241 (int-to-string (function (number) string))
242 (integer-or-marker-p (function (t) boolean)) 229 (integer-or-marker-p (function (t) boolean))
243 (integerp (function (t) boolean)) 230 (integerp (function (t) boolean))
244 (interactive-p (function () boolean))
245 (intern-soft (function ((or string symbol) &optional (or obarray vector)) 231 (intern-soft (function ((or string symbol) &optional (or obarray vector))
246 symbol)) 232 symbol))
247 (invocation-directory (function () string)) 233 (invocation-directory (function () string))
@@ -250,8 +236,6 @@ Used to modify the compiler environment."
250 (keymap-parent (function (cons) (or cons null))) 236 (keymap-parent (function (cons) (or cons null)))
251 (keymapp (function (t) boolean)) 237 (keymapp (function (t) boolean))
252 (keywordp (function (t) boolean)) 238 (keywordp (function (t) boolean))
253 (last (function (list &optional integer) list))
254 (lax-plist-get (function (list t) t))
255 (ldexp (function (number integer) float)) 239 (ldexp (function (number integer) float))
256 (length (function (t) (integer 0 *))) 240 (length (function (t) (integer 0 *)))
257 (length< (function (sequence fixnum) boolean)) 241 (length< (function (sequence fixnum) boolean))
@@ -265,7 +249,6 @@ Used to modify the compiler environment."
265 (local-variable-p (function (symbol &optional buffer) boolean)) 249 (local-variable-p (function (symbol &optional buffer) boolean))
266 (locale-info (function ((member codeset days months paper)) (or null string))) 250 (locale-info (function ((member codeset days months paper)) (or null string)))
267 (log (function (number number) float)) 251 (log (function (number number) float))
268 (log10 (function (number) float))
269 (logand (function (&rest (or integer marker)) integer)) 252 (logand (function (&rest (or integer marker)) integer))
270 (logb (function (number) integer)) 253 (logb (function (number) integer))
271 (logcount (function (integer) integer)) 254 (logcount (function (integer) integer))
@@ -273,7 +256,6 @@ Used to modify the compiler environment."
273 (lognot (function (integer) integer)) 256 (lognot (function (integer) integer))
274 (logxor (function (&rest (or integer marker)) integer)) 257 (logxor (function (&rest (or integer marker)) integer))
275 ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ? 258 ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
276 (lsh (function (integer integer) integer))
277 (make-byte-code 259 (make-byte-code
278 (function ((or fixnum list) string vector integer &optional string t 260 (function ((or fixnum list) string vector integer &optional string t
279 &rest t) 261 &rest t)
@@ -282,14 +264,12 @@ Used to modify the compiler environment."
282 (make-marker (function () marker)) 264 (make-marker (function () marker))
283 (make-string (function (integer fixnum &optional t) string)) 265 (make-string (function (integer fixnum &optional t) string))
284 (make-symbol (function (string) symbol)) 266 (make-symbol (function (string) symbol))
285 (mark (function (&optional t) (or integer null)))
286 (mark-marker (function () marker)) 267 (mark-marker (function () marker))
287 (marker-buffer (function (marker) (or buffer null))) 268 (marker-buffer (function (marker) (or buffer null)))
288 (markerp (function (t) boolean)) 269 (markerp (function (t) boolean))
289 (max (function ((or number marker) &rest (or number marker)) number)) 270 (max (function ((or number marker) &rest (or number marker)) number))
290 (max-char (function (&optional t) fixnum)) 271 (max-char (function (&optional t) fixnum))
291 (member (function (t list) list)) 272 (member (function (t list) list))
292 (memory-limit (function () integer))
293 (memq (function (t list) list)) 273 (memq (function (t list) list))
294 (memql (function (t list) list)) 274 (memql (function (t list) list))
295 (min (function ((or number marker) &rest (or number marker)) number)) 275 (min (function ((or number marker) &rest (or number marker)) number))
@@ -298,7 +278,6 @@ Used to modify the compiler environment."
298 (mod 278 (mod
299 (function ((or number marker) (or number marker)) 279 (function ((or number marker) (or number marker))
300 (or (integer 0 *) (float 0 *)))) 280 (or (integer 0 *) (float 0 *))))
301 (mouse-movement-p (function (t) boolean))
302 (multibyte-char-to-unibyte (function (fixnum) fixnum)) 281 (multibyte-char-to-unibyte (function (fixnum) fixnum))
303 (natnump (function (t) boolean)) 282 (natnump (function (t) boolean))
304 (next-window (function (&optional window t t) window)) 283 (next-window (function (&optional window t t) window))
@@ -310,9 +289,7 @@ Used to modify the compiler environment."
310 (number-or-marker-p (function (t) boolean)) 289 (number-or-marker-p (function (t) boolean))
311 (number-to-string (function (number) string)) 290 (number-to-string (function (number) string))
312 (numberp (function (t) boolean)) 291 (numberp (function (t) boolean))
313 (one-window-p (function (&optional t t) boolean))
314 (overlayp (function (t) boolean)) 292 (overlayp (function (t) boolean))
315 (parse-colon-path (function (string) list))
316 (plist-get (function (list t &optional t) t)) 293 (plist-get (function (list t &optional t) t))
317 (plist-member (function (list t &optional t) list)) 294 (plist-member (function (list t &optional t) list))
318 (point (function () integer)) 295 (point (function () integer))
@@ -325,13 +302,11 @@ Used to modify the compiler environment."
325 (processp (function (t) boolean)) 302 (processp (function (t) boolean))
326 (proper-list-p (function (t) (or fixnum null))) 303 (proper-list-p (function (t) (or fixnum null)))
327 (propertize (function (string &rest t) string)) 304 (propertize (function (string &rest t) string))
328 (radians-to-degrees (function (number) float))
329 (rassoc (function (t list) list)) 305 (rassoc (function (t list) list))
330 (rassq (function (t list) list)) 306 (rassq (function (t list) list))
331 (read-from-string (function (string &optional integer integer) cons)) 307 (read-from-string (function (string &optional integer integer) cons))
332 (recent-keys (function (&optional (or cons null)) vector)) 308 (recent-keys (function (&optional (or cons null)) vector))
333 (recursion-depth (function () integer)) 309 (recursion-depth (function () integer))
334 (regexp-opt (function (list) string))
335 (regexp-quote (function (string) string)) 310 (regexp-quote (function (string) string))
336 (region-beginning (function () integer)) 311 (region-beginning (function () integer))
337 (region-end (function () integer)) 312 (region-end (function () integer))
@@ -387,7 +362,6 @@ Used to modify the compiler environment."
387 (upcase (function ((or fixnum string)) (or fixnum string))) 362 (upcase (function ((or fixnum string)) (or fixnum string)))
388 (user-full-name (function (&optional integer) (or string null))) 363 (user-full-name (function (&optional integer) (or string null)))
389 (user-login-name (function (&optional integer) (or string null))) 364 (user-login-name (function (&optional integer) (or string null)))
390 (user-original-login-name (function (&optional integer) (or string null)))
391 (user-real-login-name (function () string)) 365 (user-real-login-name (function () string))
392 (user-real-uid (function () integer)) 366 (user-real-uid (function () integer))
393 (user-uid (function () integer)) 367 (user-uid (function () integer))
@@ -400,13 +374,8 @@ Used to modify the compiler environment."
400 (window-live-p (function (t) boolean)) 374 (window-live-p (function (t) boolean))
401 (window-valid-p (function (t) boolean)) 375 (window-valid-p (function (t) boolean))
402 (windowp (function (t) boolean)) 376 (windowp (function (t) boolean))
403 (zerop (function (number) boolean))
404 ;; Type hints
405 (comp-hint-fixnum (function (t) fixnum))
406 (comp-hint-cons (function (t) cons))
407 ;; Non returning functions 377 ;; Non returning functions
408 (throw (function (t t) nil)) 378 (throw (function (t t) nil))
409 (error (function (string &rest t) nil))
410 (signal (function (symbol t) nil))) 379 (signal (function (symbol t) nil)))
411 "Alist used for type propagation.") 380 "Alist used for type propagation.")
412 381
@@ -532,22 +501,27 @@ Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
532(defun comp-function-type-spec (function) 501(defun comp-function-type-spec (function)
533 "Return the type specifier of FUNCTION. 502 "Return the type specifier of FUNCTION.
534 503
535This function returns a cons cell whose car is the function 504This function returns a cons cell whose car is the function specifier,
536specifier, and cdr is a symbol, either `inferred' or `know'. 505and cdr is a symbol, either `inferred' or `declared'. If the symbol is
537If the symbol is `inferred', the type specifier is automatically 506`inferred', the type specifier is automatically inferred from the code
538inferred from the code itself by the native compiler; if it is 507itself by the native compiler; if it is `declared', the type specifier
539`know', the type specifier comes from `comp-known-type-specifiers'." 508comes from `comp-primitive-type-specifiers' or the function type declaration
540 (let ((kind 'know) 509itself."
541 type-spec ) 510 (let ((kind 'declared)
542 (when-let ((res (assoc function comp-known-type-specifiers))) 511 type-spec)
512 (when-let ((res (assoc function comp-primitive-type-specifiers)))
513 ;; Declared primitive
543 (setf type-spec (cadr res))) 514 (setf type-spec (cadr res)))
544 (let ((f (and (symbolp function) 515 (let ((f (and (symbolp function)
545 (symbol-function function)))) 516 (symbol-function function))))
546 (when (and f 517 (when (and f (null type-spec))
547 (null type-spec) 518 (if-let ((delc-type (function-get function 'function-type)))
548 (subr-native-elisp-p f)) 519 ;; Declared Lisp function
549 (setf kind 'inferred 520 (setf type-spec (car delc-type))
550 type-spec (subr-type f)))) 521 (when (subr-native-elisp-p f)
522 ;; Native compiled inferred
523 (setf kind 'inferred
524 type-spec (subr-type f))))))
551 (when type-spec 525 (when type-spec
552 (cons type-spec kind)))) 526 (cons type-spec kind))))
553 527
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 2ec55ed98ee..d7cd6b79c86 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -179,16 +179,24 @@ For internal use by the test suite only.")
179Each function in FUNCTIONS is run after PASS. 179Each function in FUNCTIONS is run after PASS.
180Useful to hook into pass checkers.") 180Useful to hook into pass checkers.")
181 181
182(defconst comp-known-func-cstr-h 182(defconst comp-primitive-func-cstr-h
183 (cl-loop 183 (cl-loop
184 with comp-ctxt = (make-comp-cstr-ctxt) 184 with comp-ctxt = (make-comp-cstr-ctxt)
185 with h = (make-hash-table :test #'eq) 185 with h = (make-hash-table :test #'eq)
186 for (f type-spec) in comp-known-type-specifiers 186 for (f type-spec) in comp-primitive-type-specifiers
187 for cstr = (comp-type-spec-to-cstr type-spec) 187 for cstr = (comp-type-spec-to-cstr type-spec)
188 do (puthash f cstr h) 188 do (puthash f cstr h)
189 finally return h) 189 finally return h)
190 "Hash table function -> `comp-constraint'.") 190 "Hash table function -> `comp-constraint'.")
191 191
192(defun comp--get-function-cstr (function)
193 "Given FUNCTION return the corresponding `comp-constraint'."
194 (when (symbolp function)
195 (let ((f (symbol-function function)))
196 (or (gethash f comp-primitive-func-cstr-h)
197 (when-let ((res (function-get function 'function-type)))
198 (comp-type-spec-to-cstr (car res)))))))
199
192;; Keep it in sync with the `cl-deftype-satisfies' property set in 200;; Keep it in sync with the `cl-deftype-satisfies' property set in
193;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the 201;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the
194;; relation type <-> predicate is not bijective (bug#45576). 202;; relation type <-> predicate is not bijective (bug#45576).
@@ -2102,10 +2110,10 @@ TARGET-BB-SYM is the symbol name of the target block."
2102 (when-let ((match 2110 (when-let ((match
2103 (pcase insn 2111 (pcase insn
2104 (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args)) 2112 (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args))
2105 (when-let ((cstr-f (gethash f comp-known-func-cstr-h))) 2113 (when-let ((cstr-f (comp--get-function-cstr f)))
2106 (cl-values f cstr-f lhs args))) 2114 (cl-values f cstr-f lhs args)))
2107 (`(,(pred comp--call-op-p) ,f . ,args) 2115 (`(,(pred comp--call-op-p) ,f . ,args)
2108 (when-let ((cstr-f (gethash f comp-known-func-cstr-h))) 2116 (when-let ((cstr-f (comp--get-function-cstr f)))
2109 (cl-values f cstr-f nil args)))))) 2117 (cl-values f cstr-f nil args))))))
2110 (cl-multiple-value-bind (f cstr-f lhs args) match 2118 (cl-multiple-value-bind (f cstr-f lhs args) match
2111 (cl-loop 2119 (cl-loop
@@ -2642,7 +2650,7 @@ Fold the call in case."
2642 (comp-cstr-imm-vld-p (car args))) 2650 (comp-cstr-imm-vld-p (car args)))
2643 (setf f (comp-cstr-imm (car args)) 2651 (setf f (comp-cstr-imm (car args))
2644 args (cdr args))) 2652 args (cdr args)))
2645 (when-let ((cstr-f (gethash f comp-known-func-cstr-h))) 2653 (when-let ((cstr-f (comp--get-function-cstr f)))
2646 (let ((cstr (comp-cstr-f-ret cstr-f))) 2654 (let ((cstr (comp-cstr-f-ret cstr-f)))
2647 (when (comp-cstr-empty-p cstr) 2655 (when (comp-cstr-empty-p cstr)
2648 ;; Store it to be rewritten as non local exit. 2656 ;; 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."
3301;; are assumed just to be true. Use with extreme caution... 3309;; are assumed just to be true. Use with extreme caution...
3302 3310
3303(defun comp-hint-fixnum (x) 3311(defun comp-hint-fixnum (x)
3304 (declare (gv-setter (lambda (val) `(setf ,x ,val)))) 3312 (declare (type (function (t) fixnum))
3313 (gv-setter (lambda (val) `(setf ,x ,val))))
3305 x) 3314 x)
3306 3315
3307(defun comp-hint-cons (x) 3316(defun comp-hint-cons (x)
3308 (declare (gv-setter (lambda (val) `(setf ,x ,val)))) 3317 (declare (type (function (t) cons))
3318 (gv-setter (lambda (val) `(setf ,x ,val))))
3309 x) 3319 x)
3310 3320
3311 3321
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 7e6db51b1d5..9edc11ad132 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -534,7 +534,8 @@ major mode's decisions about context.")
534 "Return the \"far end\" position of the buffer, in direction ARG. 534 "Return the \"far end\" position of the buffer, in direction ARG.
535If ARG is positive, that's the end of the buffer. 535If ARG is positive, that's the end of the buffer.
536Otherwise, that's the beginning of the buffer." 536Otherwise, that's the beginning of the buffer."
537 (declare (side-effect-free error-free)) 537 (declare (type (function ((or number marker)) integer))
538 (side-effect-free error-free))
538 (if (> arg 0) (point-max) (point-min))) 539 (if (> arg 0) (point-max) (point-min)))
539 540
540(defun end-of-defun (&optional arg interactive) 541(defun end-of-defun (&optional arg interactive)
diff --git a/lisp/emacs-lisp/regexp-opt.el b/lisp/emacs-lisp/regexp-opt.el
index 59c1b7d8e10..f23343a34c6 100644
--- a/lisp/emacs-lisp/regexp-opt.el
+++ b/lisp/emacs-lisp/regexp-opt.el
@@ -130,7 +130,8 @@ usually more efficient than that of a simplified version:
130 (concat (car parens) 130 (concat (car parens)
131 (mapconcat \\='regexp-quote strings \"\\\\|\") 131 (mapconcat \\='regexp-quote strings \"\\\\|\")
132 (cdr parens))))" 132 (cdr parens))))"
133 (declare (pure t) (side-effect-free t)) 133 (declare (type (function (list &optional t) string))
134 (pure t) (side-effect-free t))
134 (save-match-data 135 (save-match-data
135 ;; Recurse on the sorted list. 136 ;; Recurse on the sorted list.
136 (let* ((max-lisp-eval-depth 10000) 137 (let* ((max-lisp-eval-depth 10000)
diff --git a/lisp/env.el b/lisp/env.el
index e0a8df8476c..7d0c7dd0126 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -207,7 +207,8 @@ parameter.
207Otherwise, this function searches `process-environment' for 207Otherwise, this function searches `process-environment' for
208VARIABLE. If it is not found there, then it continues the search 208VARIABLE. If it is not found there, then it continues the search
209in the environment list of the selected frame." 209in the environment list of the selected frame."
210 (declare (side-effect-free t)) 210 (declare (type (function (string &optional frame) (or null string)))
211 (side-effect-free t))
211 (interactive (list (read-envvar-name "Get environment variable: " t))) 212 (interactive (list (read-envvar-name "Get environment variable: " t)))
212 (let ((value (getenv-internal (if (multibyte-string-p variable) 213 (let ((value (getenv-internal (if (multibyte-string-p variable)
213 (encode-coding-string 214 (encode-coding-string
diff --git a/lisp/files.el b/lisp/files.el
index b7ebb727c72..c24e48e3db2 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -862,6 +862,7 @@ GNU and Unix systems). Substitute environment variables into the
862resulting list of directory names. For an empty path element (i.e., 862resulting list of directory names. For an empty path element (i.e.,
863a leading or trailing separator, or two adjacent separators), return 863a leading or trailing separator, or two adjacent separators), return
864nil (meaning `default-directory') as the associated list element." 864nil (meaning `default-directory') as the associated list element."
865 (declare (type (function (string) list)))
865 (when (stringp search-path) 866 (when (stringp search-path)
866 (let ((spath (substitute-env-vars search-path)) 867 (let ((spath (substitute-env-vars search-path))
867 (double-slash-special-p 868 (double-slash-special-p
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 9bf2f61aee6..182b22549b5 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -732,7 +732,7 @@ the C sources, too."
732 (insert (format 732 (insert (format
733 (if (eq kind 'inferred) 733 (if (eq kind 'inferred)
734 "\nInferred type: %s\n" 734 "\nInferred type: %s\n"
735 "\nType: %s\n") 735 "\nDeclared type: %s\n")
736 type-spec)))) 736 type-spec))))
737 (fill-region fill-begin (point)) 737 (fill-region fill-begin (point))
738 high-doc))))) 738 high-doc)))))
diff --git a/lisp/simple.el b/lisp/simple.el
index be64f3574e0..a459f6ecfd2 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1762,7 +1762,9 @@ not at the start of a line.
1762 1762
1763When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not 1763When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not
1764included in the count." 1764included in the count."
1765 (declare (side-effect-free t)) 1765 (declare (type (function ((or integer marker) (or integer marker) &optional t)
1766 integer))
1767 (side-effect-free t))
1766 (save-excursion 1768 (save-excursion
1767 (save-restriction 1769 (save-restriction
1768 (narrow-to-region start end) 1770 (narrow-to-region start end)
@@ -6882,7 +6884,8 @@ is active, and returns an integer or nil in the usual way.
6882 6884
6883If you are using this in an editing command, you are most likely making 6885If you are using this in an editing command, you are most likely making
6884a mistake; see the documentation of `set-mark'." 6886a mistake; see the documentation of `set-mark'."
6885 (declare (side-effect-free t)) 6887 (declare (type (function (&optional t) (or integer null)))
6888 (side-effect-free t))
6886 (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive) 6889 (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
6887 (marker-position (mark-marker)) 6890 (marker-position (mark-marker))
6888 (signal 'mark-inactive nil))) 6891 (signal 'mark-inactive nil)))
@@ -11163,7 +11166,8 @@ killed."
11163 11166
11164(defun lax-plist-get (plist prop) 11167(defun lax-plist-get (plist prop)
11165 "Extract a value from a property list, comparing with `equal'." 11168 "Extract a value from a property list, comparing with `equal'."
11166 (declare (pure t) (side-effect-free t) (obsolete plist-get "29.1")) 11169 (declare (type (function (list t) t))
11170 (pure t) (side-effect-free t) (obsolete plist-get "29.1"))
11167 (plist-get plist prop #'equal)) 11171 (plist-get plist prop #'equal))
11168 11172
11169(defun lax-plist-put (plist prop val) 11173(defun lax-plist-put (plist prop val)
diff --git a/lisp/subr.el b/lisp/subr.el
index 352ecc315ef..92d1e50ab2c 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -451,7 +451,8 @@ This function accepts any number of arguments in ARGUMENTS.
451Also see `always'." 451Also see `always'."
452 ;; Not declared `side-effect-free' because we don't want calls to it 452 ;; Not declared `side-effect-free' because we don't want calls to it
453 ;; elided; see `byte-compile-ignore'. 453 ;; elided; see `byte-compile-ignore'.
454 (declare (pure t) (completion ignore)) 454 (declare (type (function (&rest t) null))
455 (pure t) (completion ignore))
455 (interactive) 456 (interactive)
456 nil) 457 nil)
457 458
@@ -480,7 +481,8 @@ for the sake of consistency.
480 481
481To alter the look of the displayed error messages, you can use 482To alter the look of the displayed error messages, you can use
482the `command-error-function' variable." 483the `command-error-function' variable."
483 (declare (advertised-calling-convention (string &rest args) "23.1")) 484 (declare (type (function (string &rest t) nil))
485 (advertised-calling-convention (string &rest args) "23.1"))
484 (signal 'error (list (apply #'format-message args)))) 486 (signal 'error (list (apply #'format-message args))))
485 487
486(defun user-error (format &rest args) 488(defun user-error (format &rest args)
@@ -545,19 +547,22 @@ was called."
545 "Return t if NUMBER is zero." 547 "Return t if NUMBER is zero."
546 ;; Used to be in C, but it's pointless since (= 0 n) is faster anyway because 548 ;; Used to be in C, but it's pointless since (= 0 n) is faster anyway because
547 ;; = has a byte-code. 549 ;; = has a byte-code.
548 (declare (pure t) (side-effect-free t) 550 (declare (type (function (number) boolean))
551 (pure t) (side-effect-free t)
549 (compiler-macro (lambda (_) `(= 0 ,number)))) 552 (compiler-macro (lambda (_) `(= 0 ,number))))
550 (= 0 number)) 553 (= 0 number))
551 554
552(defun fixnump (object) 555(defun fixnump (object)
553 "Return t if OBJECT is a fixnum." 556 "Return t if OBJECT is a fixnum."
554 (declare (side-effect-free error-free)) 557 (declare (type (function (t) boolean))
558 (side-effect-free error-free))
555 (and (integerp object) 559 (and (integerp object)
556 (<= most-negative-fixnum object most-positive-fixnum))) 560 (<= most-negative-fixnum object most-positive-fixnum)))
557 561
558(defun bignump (object) 562(defun bignump (object)
559 "Return t if OBJECT is a bignum." 563 "Return t if OBJECT is a bignum."
560 (declare (side-effect-free error-free)) 564 (declare (type (function (t) boolean))
565 (side-effect-free error-free))
561 (and (integerp object) (not (fixnump object)))) 566 (and (integerp object) (not (fixnump object))))
562 567
563(defun lsh (value count) 568(defun lsh (value count)
@@ -570,7 +575,8 @@ Most uses of this function turn out to be mistakes. We recommend
570to use `ash' instead, unless COUNT could ever be negative, and 575to use `ash' instead, unless COUNT could ever be negative, and
571if, when COUNT is negative, your program really needs the special 576if, when COUNT is negative, your program really needs the special
572treatment of negative COUNT provided by this function." 577treatment of negative COUNT provided by this function."
573 (declare (compiler-macro 578 (declare (type (function (integer integer) integer))
579 (compiler-macro
574 (lambda (form) 580 (lambda (form)
575 (macroexp-warn-and-return 581 (macroexp-warn-and-return
576 (format-message "avoid `lsh'; use `ash' instead") 582 (format-message "avoid `lsh'; use `ash' instead")
@@ -748,7 +754,8 @@ treatment of negative COUNT provided by this function."
748If LIST is nil, return nil. 754If LIST is nil, return nil.
749If N is non-nil, return the Nth-to-last link of LIST. 755If N is non-nil, return the Nth-to-last link of LIST.
750If N is bigger than the length of LIST, return LIST." 756If N is bigger than the length of LIST, return LIST."
751 (declare (pure t) (side-effect-free t)) ; pure up to mutation 757 (declare (type (function (list &optional integer) list))
758 (pure t) (side-effect-free t)) ; pure up to mutation
752 (if n 759 (if n
753 (and (>= n 0) 760 (and (>= n 0)
754 (let ((m (safe-length list))) 761 (let ((m (safe-length list)))
@@ -1585,7 +1592,8 @@ See also `current-global-map'.")
1585 1592
1586(defun eventp (object) 1593(defun eventp (object)
1587 "Return non-nil if OBJECT is an input event or event object." 1594 "Return non-nil if OBJECT is an input event or event object."
1588 (declare (pure t) (side-effect-free error-free)) 1595 (declare (type (function (t) boolean))
1596 (pure t) (side-effect-free error-free))
1589 (or (integerp object) 1597 (or (integerp object)
1590 (and (if (consp object) 1598 (and (if (consp object)
1591 (setq object (car object)) 1599 (setq object (car object))
@@ -1652,7 +1660,8 @@ in the current Emacs session, then this function may return nil."
1652 1660
1653(defsubst mouse-movement-p (object) 1661(defsubst mouse-movement-p (object)
1654 "Return non-nil if OBJECT is a mouse movement event." 1662 "Return non-nil if OBJECT is a mouse movement event."
1655 (declare (side-effect-free error-free)) 1663 (declare (type (function (t) boolean))
1664 (side-effect-free error-free))
1656 (eq (car-safe object) 'mouse-movement)) 1665 (eq (car-safe object) 'mouse-movement))
1657 1666
1658(defun mouse-event-p (object) 1667(defun mouse-event-p (object)
@@ -1961,7 +1970,8 @@ be a list of the form returned by `event-start' and `event-end'."
1961 1970
1962(defun log10 (x) 1971(defun log10 (x)
1963 "Return (log X 10), the log base 10 of X." 1972 "Return (log X 10), the log base 10 of X."
1964 (declare (side-effect-free t) (obsolete log "24.4")) 1973 (declare (type (function (number) float))
1974 (side-effect-free t) (obsolete log "24.4"))
1965 (log x 10)) 1975 (log x 10))
1966 1976
1967(set-advertised-calling-convention 1977(set-advertised-calling-convention
@@ -3245,7 +3255,8 @@ It can be retrieved with `(process-get PROCESS PROPNAME)'."
3245 3255
3246(defun memory-limit () 3256(defun memory-limit ()
3247 "Return an estimate of Emacs virtual memory usage, divided by 1024." 3257 "Return an estimate of Emacs virtual memory usage, divided by 1024."
3248 (declare (side-effect-free error-free)) 3258 (declare (type (function () integer))
3259 (side-effect-free error-free))
3249 (let ((default-directory temporary-file-directory)) 3260 (let ((default-directory temporary-file-directory))
3250 (or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0))) 3261 (or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0)))
3251 3262
@@ -6467,7 +6478,8 @@ To test whether a function can be called interactively, use
6467`commandp'." 6478`commandp'."
6468 ;; Kept around for now. See discussion at: 6479 ;; Kept around for now. See discussion at:
6469 ;; https://lists.gnu.org/r/emacs-devel/2020-08/msg00564.html 6480 ;; https://lists.gnu.org/r/emacs-devel/2020-08/msg00564.html
6470 (declare (obsolete called-interactively-p "23.2") 6481 (declare (type (function () boolean))
6482 (obsolete called-interactively-p "23.2")
6471 (side-effect-free error-free)) 6483 (side-effect-free error-free))
6472 (called-interactively-p 'interactive)) 6484 (called-interactively-p 'interactive))
6473 6485
diff --git a/lisp/window.el b/lisp/window.el
index cdc6f690bab..639090752be 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2515,7 +2515,8 @@ have special meanings:
2515 2515
2516Any other value of ALL-FRAMES means consider all windows on the 2516Any other value of ALL-FRAMES means consider all windows on the
2517selected frame and no others." 2517selected frame and no others."
2518 (declare (side-effect-free error-free)) 2518 (declare (type (function (&optional t t t) (or window null)))
2519 (side-effect-free error-free))
2519 (let ((windows (window-list-1 nil 'nomini all-frames)) 2520 (let ((windows (window-list-1 nil 'nomini all-frames))
2520 best-window best-time second-best-window second-best-time time) 2521 best-window best-time second-best-window second-best-time time)
2521 (dolist (window windows) 2522 (dolist (window windows)
@@ -2594,7 +2595,8 @@ have special meanings:
2594 2595
2595Any other value of ALL-FRAMES means consider all windows on the 2596Any other value of ALL-FRAMES means consider all windows on the
2596selected frame and no others." 2597selected frame and no others."
2597 (declare (side-effect-free error-free)) 2598 (declare (type (function (&optional t t t) (or window null)))
2599 (side-effect-free error-free))
2598 (let ((best-size 0) 2600 (let ((best-size 0)
2599 best-window size) 2601 best-window size)
2600 (dolist (window (window-list-1 nil 'nomini all-frames)) 2602 (dolist (window (window-list-1 nil 'nomini all-frames))
@@ -4089,7 +4091,8 @@ with a special meaning are:
4089 4091
4090Anything else means consider all windows on the selected frame 4092Anything else means consider all windows on the selected frame
4091and no others." 4093and no others."
4092 (declare (side-effect-free error-free)) 4094 (declare (type (function (&optional t t) boolean))
4095 (side-effect-free error-free))
4093 (let ((base-window (selected-window))) 4096 (let ((base-window (selected-window)))
4094 (if (and nomini (eq base-window (minibuffer-window))) 4097 (if (and nomini (eq base-window (minibuffer-window)))
4095 (setq base-window (next-window base-window))) 4098 (setq base-window (next-window base-window)))