Don't rewrite set to setq of lexical variables

Only perform the rewrite

   (set 'VAR X) -> (setq VAR X)

for dynamic variables, as `set` isn't supposed to affect
lexical vars (and never does so when interpreted).

* lisp/emacs-lisp/byte-opt.el (byte-optimize-set):
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--xx): New.
(bytecomp-tests--test-cases): Add test cases.
* test/lisp/emacs-lisp/bytecomp-resources/warn-variable-set-nonvariable.el:
Remove obsolete test.
This commit is contained in:
Mattias Engdegård 2022-09-22 14:15:56 +02:00
parent e9f42b1cba
commit e4964de952
3 changed files with 22 additions and 15 deletions

View file

@ -1531,15 +1531,16 @@ See Info node `(elisp) Integer Basics'."
(put 'set 'byte-optimizer #'byte-optimize-set)
(defun byte-optimize-set (form)
(let ((var (car-safe (cdr-safe form))))
(cond
((and (eq (car-safe var) 'quote) (consp (cdr var)))
`(setq ,(cadr var) ,@(cddr form)))
((and (eq (car-safe var) 'make-local-variable)
(eq (car-safe (setq var (car-safe (cdr var)))) 'quote)
(consp (cdr var)))
`(progn ,(cadr form) (setq ,(cadr var) ,@(cddr form))))
(t form))))
(pcase (cdr form)
;; Make sure we only turn `set' into `setq' for dynamic variables.
(`((quote ,(and var (guard (and (symbolp var)
(not (macroexp--const-symbol-p var))
(not (assq var byte-optimize--lexvars))))))
,newval)
`(setq ,var ,newval))
(`(,(and ml `(make-local-variable ,(and v `(quote ,_)))) ,newval)
`(progn ,ml (,(car form) ,v ,newval)))
(_ form)))
;; enumerating those functions which need not be called if the returned
;; value is not used. That is, something like

View file

@ -1,3 +0,0 @@
;;; -*- lexical-binding: t -*-
(defun foo ()
(set '(a) nil))

View file

@ -59,6 +59,8 @@ inner loops respectively."
(setq i (1- i)))
res))
(defvar bytecomp-tests--xx nil)
(defconst bytecomp-tests--test-cases
'(
;; some functional tests
@ -692,6 +694,16 @@ inner loops respectively."
(f (lambda ()
(let ((y x)) (list y 3 y)))))
(funcall f))
;; Test rewriting of `set' to `setq' (only done on dynamic variables).
(let ((xx 1)) (set 'xx 2) xx)
(let ((bytecomp-tests--xx 1))
(set 'bytecomp-tests--xx 2)
bytecomp-tests--xx)
(let ((aaa 1)) (set (make-local-variable 'aaa) 2) aaa)
(let ((bytecomp-tests--xx 1))
(set (make-local-variable 'bytecomp-tests--xx) 2)
bytecomp-tests--xx)
)
"List of expressions for cross-testing interpreted and compiled code.")
@ -953,9 +965,6 @@ byte-compiled. Run with dynamic binding."
(bytecomp--define-warning-file-test "warn-variable-set-constant.el"
"attempt to set constant")
(bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el"
"variable reference to nonvariable")
(bytecomp--define-warning-file-test "warn-variable-setq-nonvariable.el"
"attempt to set non-variable")