GNU bug report logs - #10761
24.0.93; variable declared with defvar is not recognized as special

Previous Next

Package: emacs;

Reported by: Oleksandr Manzyuk <manzyuk <at> gmail.com>

Date: Wed, 8 Feb 2012 09:24:02 UTC

Severity: normal

Found in version 24.0.93

Done: Stefan Monnier <monnier <at> IRO.UMontreal.CA>

Bug is archived. No further changes may be made.

Full log


Message #10 received at 10761-done <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Oleksandr Manzyuk <manzyuk <at> gmail.com>
Cc: 10761-done <at> debbugs.gnu.org
Subject: Re: bug#10761: 24.0.93;
	variable declared with defvar is not recognized as special
Date: Thu, 09 Feb 2012 16:52:20 -0500
> 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 <at> 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 <at> 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)





This bug report was last modified 13 years and 188 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.