The current method of propagating constants through setq was unsound
because it relied on each setq form only being traversed at most once
during optimisation, which isn't necessarily true in general; it could
be made to miscompile code in rare cases.
Since it was only used in limited circumstances, disabling this
optimisation doesn't cost us much.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
Don't update the known value when traversing `setq`.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
Add test case.
(lexvar (assq var byte-optimize--lexvars))
(value (byte-optimize-form expr nil)))
(when lexvar
- ;; Set a new value or inhibit further substitution.
- (setcdr (cdr lexvar)
- (and
- ;; Inhibit if bound outside conditional code.
- (not (assq var byte-optimize--vars-outside-condition))
- ;; The new value must be substitutable.
- (byte-optimize--substitutable-p value)
- (list value)))
- (setcar (cdr lexvar) t)) ; Mark variable to be kept.
+ (setcar (cdr lexvar) t) ; Mark variable to be kept.
+ (setcdr (cdr lexvar) nil)) ; Inhibit further substitution.
+
(push var var-expr-list)
(push value var-expr-list))
(setq args (cddr args)))
(let ((x 2))
(list (or (bytecomp-test-identity 'a) (setq x 3)) x))
+ (mapcar (lambda (b)
+ (let ((a nil))
+ (+ 0
+ (progn
+ (setq a b)
+ (setq b 1)
+ a))))
+ '(10))
+
(let* ((x 1)
(y (condition-case x
(/ 1 0)