Merge branch 'lisp-func-type-decls' into 'master'
This commit is contained in:
commit
da8b06bd61
14 changed files with 147 additions and 76 deletions
|
@ -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,
|
||||||
|
|
5
etc/NEWS
5
etc/NEWS
|
@ -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'
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))))
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)))))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
36
lisp/subr.el
36
lisp/subr.el
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue