Subject: Dynamic scoping is all weird now?

From: Dave Goel <[email-masked]>
Date: Sun, 5 Nov 2023 00:06:49 -0400

I was playing around, checking my sanity re : dynamic scoping.  I'm
probably rusty, but I could swear that on older emacsen, this sort of code
would print 33 ten times.

On emacs -Q with debian stable (28.2).
I try this

(progn
  (setq lexical-binding nil)

  (dotimes (ii 10)
    (defmacro mac ()
      `(message "%S" ,ii)
      (sit-for 0.1))
    (let ((old_ii ii))
      (setq ii 33)
      (mac)
      (setq ii old_ii)
      )))

Exits without error the first two times, although, strangely, i don't see
any messages the second time. (I expected to see ten 33's).

*(a) As in, the second time, it doesn't print 33 ten times, as we would
expect.*
*(b) The third time is stranger. *
Let's evaluate it a third time! The third time is even weirder.
The third time, it complains
Debugger entered--Lisp error: (void-variable ii)
  (list 'message "%S" ii)
  (lambda nil (list 'message "%S" ii) (list 'print ii) (sit-for 0.1))()
  macroexpand((mac) nil)
  macroexp-macroexpand((mac) nil)
  macroexp--expand-all((mac))
  macroexp--all-forms(((setq ii 33) (mac) (setq ii old_ii)))
  macroexp--expand-all((let ((old_ii ii)) (setq ii 33) (mac) (setq ii
old_ii)))

and so on.

The bug(?) was reproduced on 29.1 as well - by e1f on #emacs

*(c) It gets even funnier. e1f changed ii to var, but the third time, it
still complained about ii, with the above error message, and not about var.*
I reproduced that as well.

Dave