bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#10761: 24.0.93; variable declared with defvar is not recognized as s


From: Stefan Monnier
Subject: bug#10761: 24.0.93; variable declared with defvar is not recognized as special
Date: Thu, 09 Feb 2012 16:52:20 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux)

> 1. emacs -Q
> 2. M-: (boundp 'pcomplete-stub) RET ==> nil
> 3. M-x shell
> 4. M-: (boundp 'pcomplete-stub) RET ==> t
> 5. M-: (special-variable-p 'pcomplete-stub) RET ==> nil
> 6. Open the file `pcomplete.el' (for example, by looking up the variable
> `pcomplete-stub') and M-x eval-buffer.  Now (special-variable-p
> 'pcomplete-stub) evaluates to t.

Thanks for catching this.  It's actually a pretty bad bug.
I've installed the patch below which I believe fixes the problem,


        Stefan


=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog      2012-02-09 20:27:54 +0000
+++ lisp/ChangeLog      2012-02-09 21:50:23 +0000
@@ -1,3 +1,11 @@
+2012-02-09  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * emacs-lisp/bytecomp.el (byte-compile-file-form-defvar):
+       Don't fallback on byte-compile-defvar.  Optimize (defvar foo) away.
+       (byte-compile-tmp-var): New const.
+       (byte-compile-defvar): Use it to minimize .elc size.
+       Just use `defvar' rather than simulate it (bug#10761).
+
 2012-02-09  Glenn Morris  <rgm@gnu.org>
 
        * files.el (rename-uniquely): Doc fix.  (Bug#3806)

=== modified file 'lisp/emacs-lisp/bytecomp.el'
--- lisp/emacs-lisp/bytecomp.el 2012-01-19 07:21:25 +0000
+++ lisp/emacs-lisp/bytecomp.el 2012-02-09 19:09:21 +0000
@@ -2237,10 +2237,6 @@
 (put 'defvar   'byte-hunk-handler 'byte-compile-file-form-defvar)
 (put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar)
 (defun byte-compile-file-form-defvar (form)
-  (if (null (nth 3 form))
-      ;; Since there is no doc string, we can compile this as a normal form,
-      ;; and not do a file-boundary.
-      (byte-compile-keep-pending form)
     (when (and (symbolp (nth 1 form))
                (not (string-match "[-*/:$]" (symbol-name (nth 1 form))))
                (byte-compile-warning-enabled-p 'lexical))
@@ -2249,6 +2245,9 @@
     (push (nth 1 form) byte-compile-bound-variables)
     (if (eq (car form) 'defconst)
        (push (nth 1 form) byte-compile-const-variables))
+  (if (and (null (cddr form))          ;No `value' provided.
+           (eq (car form) 'defvar))     ;Just a declaration.
+      nil
     (cond ((consp (nth 2 form))
           (setq form (copy-sequence form))
           (setcar (cdr (cdr form))
@@ -4124,8 +4123,10 @@
     (push (nth 1 (nth 1 form)) byte-compile-global-not-obsolete-vars))
   (byte-compile-normal-call form))
 
+(defconst byte-compile-tmp-var (make-symbol "def-tmp-var"))
+
 (defun byte-compile-defvar (form)
-  ;; This is not used for file-level defvar/consts with doc strings.
+  ;; This is not used for file-level defvar/consts.
   (when (and (symbolp (nth 1 form))
              (not (string-match "[-*/:$]" (symbol-name (nth 1 form))))
              (byte-compile-warning-enabled-p 'lexical))
@@ -4148,32 +4149,21 @@
     (push var byte-compile-bound-variables)
     (if (eq fun 'defconst)
        (push var byte-compile-const-variables))
-    (byte-compile-body-do-effect
-     (list
-      ;; Put the defined variable in this library's load-history entry
-      ;; just as a real defvar would, but only in top-level forms.
-      (when (and (cddr form) (null byte-compile-current-form))
-       `(setq current-load-list (cons ',var current-load-list)))
-      (when (> (length form) 3)
        (when (and string (not (stringp string)))
            (byte-compile-warn "third arg to `%s %s' is not a string: %s"
                               fun var string))
-       `(put ',var 'variable-documentation ,string))
+    (byte-compile-form-do-effect
       (if (cddr form)          ; `value' provided
-         (let ((byte-compile-not-obsolete-vars (list var)))
-           (if (eq fun 'defconst)
-               ;; `defconst' sets `var' unconditionally.
-               (let ((tmp (make-symbol "defconst-tmp-var")))
                   ;; Quote with `quote' to prevent byte-compiling the body,
                   ;; which would lead to an inf-loop.
-                 `(funcall '(lambda (,tmp) (defconst ,var ,tmp))
-                           ,value))
-             ;; `defvar' sets `var' only when unbound.
-             `(if (not (default-boundp ',var)) (setq-default ,var ,value))))
-       (when (eq fun 'defconst)
+         `(funcall '(lambda (,byte-compile-tmp-var)
+                      (,fun ,var ,byte-compile-tmp-var ,@(nthcdr 3 form)))
+                   ,value)
+        (if (eq fun 'defconst)
          ;; This will signal an appropriate error at runtime.
-         `(eval ',form)))
-      `',var))))
+            `(eval ',form)
+          ;; A simple (defvar foo) just returns foo.
+          `',var)))))
 
 (defun byte-compile-autoload (form)
   (byte-compile-set-symbol-position 'autoload)






reply via email to

[Prev in Thread] Current Thread [Next in Thread]