aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2022-01-31 11:07:06 -0500
committerStefan Monnier2022-01-31 11:07:26 -0500
commit1d1b664fbb9232aa40d8daa54a689cfd63d38aa9 (patch)
tree164ad10242c8566c3c8fa1d0c12c50804f82d791 /src
parent90bbf27f02b1e7bf9cc0f0206313795c210c565b (diff)
downloademacs-1d1b664fbb9232aa40d8daa54a689cfd63d38aa9.tar.gz
emacs-1d1b664fbb9232aa40d8daa54a689cfd63d38aa9.zip
(function-history): New symbol property (bug#53632)
Rework the code we have in Fdefalias that tries to keep track of definitions so as to be able to undo them later. We used to store in `load-history` when an autoload is redefined as a non-autoload and in the `autoload` symbol property we used to store the autoload data that used to be used before it got overriden. Instead, store the history of the function definition of a symbol in its `function-history` symbol property. To make this list cheap in the default case, the latest value is not stored in the list (since it's in the `symbol-function`) and neither is the first file. So if there's only been a single definition (the most common case), the list is empty and the property is just not present at all. The patch also gets rid of the `autoload` vs `defun` distinction in `load-history` which seems unnecessary (a significant part of the motivation for this patch was to get rid of the special handling of autoloads in this part of the code). * src/data.c (add_to_function_history): New function. (defalias): Use it. Don't add the `t` entries for autoloads and always use `defun` regardless of the kind of definition. Change `Vautoload_queue` to only hold the function symbols since the rest is now available from `function-history`. * src/eval.c (un_autoload): Adjust accordingly. * src/lread.c (load-history): Udate docstring. * lisp/loadhist.el (loadhist-unload-filename): New var. (unload-feature): Bind it. (loadhist-unload-element): Document its availability. (loadhist--restore-autoload): Delete var. (loadhist--unload-function): Delete function. (loadhist-unload-element): Delete the `t` and `autoload` methods. Rewrite the `defun` method using `function-history`. * lisp/help-fns.el: Require `seq`. (help-fns--autoloaded-p): Rewrite. (help-fns-function-description-header): Adjust call accordingly. * doc/lispref/loading.texi (Where Defined): Remove `autoload` and `t` entries from `load-history` since we don't generate them any more. Document the `function-history` which replaces the `autoload` property. (Unloading): Adjust symbol property name accordingly. * test/lisp/loadhist-resources/loadhist--bar.el: * test/lisp/loadhist-resources/loadhist--foo.el: New files. * test/lisp/loadhist-tests.el (loadhist-tests-unload-feature-nested) (loadhist-tests-unload-feature-notnested): New tests.
Diffstat (limited to 'src')
-rw-r--r--src/data.c62
-rw-r--r--src/eval.c14
-rw-r--r--src/lread.c9
3 files changed, 58 insertions, 27 deletions
diff --git a/src/data.c b/src/data.c
index a5a76a27554..95d29ac9e98 100644
--- a/src/data.c
+++ b/src/data.c
@@ -859,6 +859,43 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
859 return definition; 859 return definition;
860} 860}
861 861
862static void
863add_to_function_history (Lisp_Object symbol, Lisp_Object olddef)
864{
865 eassert (!NILP (olddef));
866
867 Lisp_Object past = Fget (symbol, Qfunction_history);
868 Lisp_Object file = Qnil;
869 /* FIXME: Sadly, `Vload_file_name` gives less precise information
870 (it's sometimes non-nil when it shoujld be nil). */
871 Lisp_Object tail = Vcurrent_load_list;
872 FOR_EACH_TAIL_SAFE (tail)
873 if (NILP (XCDR (tail)) && STRINGP (XCAR (tail)))
874 file = XCAR (tail);
875
876 Lisp_Object tem = Fplist_member (past, file);
877 if (!NILP (tem))
878 { /* New def from a file used before.
879 Overwrite the previous record associated with this file. */
880 if (EQ (tem, past))
881 /* The new def is from the same file as the last change, so
882 there's nothing to do: unloading the file should revert to
883 the status before the last change rather than before this load. */
884 return;
885 Lisp_Object pastlen = Flength (past);
886 Lisp_Object temlen = Flength (tem);
887 EMACS_INT tempos = XFIXNUM (pastlen) - XFIXNUM (temlen);
888 eassert (tempos > 1);
889 Lisp_Object prev = Fnthcdr (make_fixnum (tempos - 2), past);
890 /* Remove the previous info for this file.
891 E.g. change `hist` from (... OTHERFILE DEF3 THISFILE DEF2 ...)
892 to (... OTHERFILE DEF2). */
893 XSETCDR (prev, XCDR (tem));
894 }
895 /* Push new def from new file. */
896 Fput (symbol, Qfunction_history, Fcons (file, Fcons (olddef, past)));
897}
898
862void 899void
863defalias (Lisp_Object symbol, Lisp_Object definition) 900defalias (Lisp_Object symbol, Lisp_Object definition)
864{ 901{
@@ -866,19 +903,19 @@ defalias (Lisp_Object symbol, Lisp_Object definition)
866 bool autoload = AUTOLOADP (definition); 903 bool autoload = AUTOLOADP (definition);
867 if (!will_dump_p () || !autoload) 904 if (!will_dump_p () || !autoload)
868 { /* Only add autoload entries after dumping, because the ones before are 905 { /* Only add autoload entries after dumping, because the ones before are
869 not useful and else we get loads of them from the loaddefs.el. */ 906 not useful and else we get loads of them from the loaddefs.el.
870 Lisp_Object function = XSYMBOL (symbol)->u.s.function; 907 That saves us about 110KB in the pdmp file (Jan 2022). */
871 908 LOADHIST_ATTACH (Fcons (Qdefun, symbol));
872 if (AUTOLOADP (function)) 909 }
873 /* Remember that the function was already an autoload. */ 910 }
874 LOADHIST_ATTACH (Fcons (Qt, symbol));
875 LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol));
876
877 if (!NILP (Vautoload_queue) && !NILP (function))
878 Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue);
879 911
880 if (AUTOLOADP (function)) 912 {
881 Fput (symbol, Qautoload, XCDR (function)); 913 Lisp_Object olddef = XSYMBOL (symbol)->u.s.function;
914 if (!NILP (olddef))
915 {
916 if (!NILP (Vautoload_queue))
917 Vautoload_queue = Fcons (symbol, Vautoload_queue);
918 add_to_function_history (symbol, olddef);
882 } 919 }
883 } 920 }
884 921
@@ -4171,6 +4208,7 @@ syms_of_data (void)
4171 4208
4172 DEFSYM (Qinteractive_form, "interactive-form"); 4209 DEFSYM (Qinteractive_form, "interactive-form");
4173 DEFSYM (Qdefalias_fset_function, "defalias-fset-function"); 4210 DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
4211 DEFSYM (Qfunction_history, "function-history");
4174 4212
4175 DEFSYM (Qbyte_code_function_p, "byte-code-function-p"); 4213 DEFSYM (Qbyte_code_function_p, "byte-code-function-p");
4176 4214
diff --git a/src/eval.c b/src/eval.c
index b083a00a791..1076985d097 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2250,21 +2250,17 @@ this does nothing and returns nil. */)
2250static void 2250static void
2251un_autoload (Lisp_Object oldqueue) 2251un_autoload (Lisp_Object oldqueue)
2252{ 2252{
2253 Lisp_Object queue, first, second;
2254
2255 /* Queue to unwind is current value of Vautoload_queue. 2253 /* Queue to unwind is current value of Vautoload_queue.
2256 oldqueue is the shadowed value to leave in Vautoload_queue. */ 2254 oldqueue is the shadowed value to leave in Vautoload_queue. */
2257 queue = Vautoload_queue; 2255 Lisp_Object queue = Vautoload_queue;
2258 Vautoload_queue = oldqueue; 2256 Vautoload_queue = oldqueue;
2259 while (CONSP (queue)) 2257 while (CONSP (queue))
2260 { 2258 {
2261 first = XCAR (queue); 2259 Lisp_Object first = XCAR (queue);
2262 second = Fcdr (first); 2260 if (CONSP (first) && EQ (XCAR (first), make_fixnum (0)))
2263 first = Fcar (first); 2261 Vfeatures = XCDR (first);
2264 if (EQ (first, make_fixnum (0)))
2265 Vfeatures = second;
2266 else 2262 else
2267 Ffset (first, second); 2263 Ffset (first, Fcar (Fcdr (Fget (first, Qfunction_history))));
2268 queue = XCDR (queue); 2264 queue = XCDR (queue);
2269 } 2265 }
2270} 2266}
diff --git a/src/lread.c b/src/lread.c
index 9910db27de7..713c03243cb 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -5240,12 +5240,9 @@ for symbols and features not associated with any file.
5240The remaining ENTRIES in the alist element describe the functions and 5240The remaining ENTRIES in the alist element describe the functions and
5241variables defined in that file, the features provided, and the 5241variables defined in that file, the features provided, and the
5242features required. Each entry has the form `(provide . FEATURE)', 5242features required. Each entry has the form `(provide . FEATURE)',
5243`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', 5243`(require . FEATURE)', `(defun . FUNCTION)', `(defface . SYMBOL)',
5244`(defface . SYMBOL)', `(define-type . SYMBOL)', 5244 `(define-type . SYMBOL)', or `(cl-defmethod METHOD SPECIALIZERS)'.
5245`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. 5245In addition, entries may also be single symbols,
5246Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry,
5247and mean that SYMBOL was an autoload before this file redefined it
5248as a function. In addition, entries may also be single symbols,
5249which means that symbol was defined by `defvar' or `defconst'. 5246which means that symbol was defined by `defvar' or `defconst'.
5250 5247
5251During preloading, the file name recorded is relative to the main Lisp 5248During preloading, the file name recorded is relative to the main Lisp