diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2023-02-20 15:23:12 +0100 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2023-02-21 10:42:00 +0100 |
commit | db3fea2e5ce46229ae40aa9ca6a89964261a7a5a (patch) | |
tree | 43264b77f2bc165a310090c40065ee6dfc750169 /lisp/subr.el | |
parent | c4c4af022d6091537fb0d748342eba5e7d3ddd23 (diff) | |
download | emacs-db3fea2e5ce46229ae40aa9ca6a89964261a7a5a.tar.gz |
Detect and prevent function alias loops in `fset` and `defalias`
Make `fset` and `defalias` signal an error on attempts to create
circular alias chains. This is more effective, efficient and
convenient than permitting alias loops to be created and trying to
detect them at run time each time a function is called, which is what
we have been doing until now, badly.
* lisp/help-fns.el (help-fns--analyze-function):
Don't pass obsolete argument.
* lisp/subr.el (function-alias-p):
* src/data.c (indirect_function, Findirect_function): Simplify.
Now error-free, second argument obsolete.
(Ffset): Detect loops.
* test/lisp/help-fns-tests.el (help-fns--analyze-function-recursive):
* test/lisp/subr-tests.el (test-alias-p):
Adapt tests.
* test/src/data-tests.el (data-tests-fset, data-tests-defalias): New.
* doc/lispref/eval.texi (Function Indirection):
* doc/lispref/functions.texi (Defining Functions, Function Cells):
Update manual.
* etc/NEWS: Announce.
Diffstat (limited to 'lisp/subr.el')
-rw-r--r-- | lisp/subr.el | 30 |
1 files changed, 10 insertions, 20 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 1a4ecc08931..916b6de494b 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -7002,27 +7002,17 @@ string will be displayed only if BODY takes longer than TIMEOUT seconds. (lambda () ,@body))) -(defun function-alias-p (func &optional noerror) +(defun function-alias-p (func &optional _noerror) "Return nil if FUNC is not a function alias. -If FUNC is a function alias, return the function alias chain. - -If the function alias chain contains loops, an error will be -signaled. If NOERROR, the non-loop parts of the chain is returned." - (declare (side-effect-free t)) - (let ((chain nil) - (orig-func func)) - (nreverse - (catch 'loop - (while (and (symbolp func) - (setq func (symbol-function func)) - (symbolp func)) - (when (or (memq func chain) - (eq func orig-func)) - (if noerror - (throw 'loop chain) - (signal 'cyclic-function-indirection (list orig-func)))) - (push func chain)) - chain)))) +If FUNC is a function alias, return the function alias chain." + (declare (advertised-calling-convention (func) "30.1") + (side-effect-free error-free)) + (let ((chain nil)) + (while (and (symbolp func) + (setq func (symbol-function func)) + (symbolp func)) + (push func chain)) + (nreverse chain))) (defun readablep (object) "Say whether OBJECT has a readable syntax. |