From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Luc Teirlinck Newsgroups: gmane.emacs.devel Subject: Bugs in two functions using load-history. Date: Thu, 18 Jul 2002 20:57:46 -0500 (CDT) Sender: emacs-devel-admin@gnu.org Message-ID: <200207190157.UAA07627@eel.dms.auburn.edu> NNTP-Posting-Host: localhost.gmane.org X-Trace: main.gmane.org 1027043889 26061 127.0.0.1 (19 Jul 2002 01:58:09 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Fri, 19 Jul 2002 01:58:09 +0000 (UTC) Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.33 #1 (Debian)) id 17VN20-0006mE-00 for ; Fri, 19 Jul 2002 03:58:08 +0200 Original-Received: from fencepost.gnu.org ([199.232.76.164]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 17VNEA-0006U5-00 for ; Fri, 19 Jul 2002 04:10:42 +0200 Original-Received: from localhost ([127.0.0.1] helo=fencepost.gnu.org) by fencepost.gnu.org with esmtp (Exim 3.35 #1 (Debian)) id 17VN1m-0007d5-00; Thu, 18 Jul 2002 21:57:54 -0400 Original-Received: from manatee.dms.auburn.edu ([131.204.53.104]) by fencepost.gnu.org with esmtp (Exim 3.35 #1 (Debian)) id 17VN0m-0007S5-00 for ; Thu, 18 Jul 2002 21:56:52 -0400 Original-Received: from eel.dms.auburn.edu (eel.dms.auburn.edu [131.204.53.108]) by manatee.dms.auburn.edu (8.9.1a/8.9.1) with ESMTP id UAA21093 for ; Thu, 18 Jul 2002 20:56:51 -0500 (CDT) Original-Received: (from teirllm@localhost) by eel.dms.auburn.edu (8.9.3+Sun/8.9.3) id UAA07627; Thu, 18 Jul 2002 20:57:46 -0500 (CDT) X-Authentication-Warning: eel.dms.auburn.edu: teirllm set sender to teirllm@dms.auburn.edu using -f Original-To: emacs-devel@gnu.org Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:5882 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:5882 I am using emacs21.2.90. I found bugs in two functions resulting from an inappropriate use of load-history. The two bugs are unrelated but have exactly the same cause. One is very nasty. The two functions are symbol-file and unload-feature. The basic problem that underlies the two bugs is that load-history records which file defined which symbols, without any record of whether they were defined as variables or as functions. This latter information would appear to be essential for most correct uses of load-history. To see both bugs do the following. Start a new emacs-q. Do M-: (symbol-file '*) Result: nil. (Of course: built-in function) M-: (load "ielm") M-: (symbol-file '*) Result: "ielm" Ielm defines a variable *, not the function *. Symbol-file is supposed to return the file defining the function *. (Otherwise, describe-function should not use it.) Hence this is a bug. This bug as implications at the user level. For instance, after loading ielm.elc, C-h f * claims that the function * is defined in ielm: * is a built-in function in `ielm'. (* &rest NUMBERS-OR-MARKERS) Returns product of any number of arguments, which are numbers or markers. In emacs21.2.90, things get worse from here. Let us unload ielm: M-: (unload-feature 'ielm) M-: (* 2 3) void-function error. M-: (fboundp '*) Result: nil. I explicitly referred to Emacs21.2.90, because in Emacs20.7, we not only get the expected answers, but, moreover: M-: (symbol-file '*) now again returns nil. Nevertheless, unload-feature has a bug in Emacs20.7 too, which is probably why the code got changed in Emacs21. However, the fix made things worse. I know exactly what the cause for the bugs in symbol-file and unload-feature is, but I am less sure about the best solution. One could redefine load-history so that it distinguishes between variable and function definitions. Alternatively, one could make the functions that use load-history, such as symbol-file and unload-feature (or, alternatively, the function feature-symbols called by unload-feature) check whether any symbol-file association they found in load-history was due to a variable definition, a function definition or both. Here is the bug in the Emacs21.2.90 version of unload-feature. The bug in the smaller function symbol-file has a similar cause: (mapc (lambda (x) (cond ((stringp x) nil) ((consp x) ;; Remove any feature names that this file provided. (if (eq (car x) 'provide) (setq features (delq (cdr x) features)))) (t (when (boundp x) (makunbound x)) (when (fboundp x) (if (fboundp 'ad-unadvise) (ad-unadvise x)) (fmakunbound x) (let ((aload (get x 'autoload))) (if aload (fset x (cons 'autoload aload)))))))) (cdr flist)) This is a piece of code from unload-feature (lines 161-177 in loadhist.c in emacs21.2.90). Note that both makunbound and fmakunbound get called on any symbol x found in the file by load-history, as long as it satisfies boundp or fboundp, respectively. This is why the function * becomes undefined after (unload-feature 'ielm) Here is the bug in the Emacs20.7 version. The fact that it handles * correctly is a coincidence: (mapcar (lambda (x) (cond ((stringp x) nil) ((consp x) ;; Remove any feature names that this file provided. (if (eq (car x) 'provide) (setq features (delq (cdr x) features)))) ((boundp x) (makunbound x)) ((fboundp x) (fmakunbound x) (let ((aload (get x 'autoload))) (if aload (fset x (cons 'autoload aload))))))) (cdr flist)) This has a differently structured cond. It does not produce bugs if the file defined x as a variable, but not as a function, which is exactly what happens in the *-ielm example, but it does produce bugs in several other situations. There is absolutely no way whatsoever that unload-feature can handle all situations correctly without checking whether the file itself defined x as a variable, a function or both. Sincerely, Luc.