Subject: bug#27674: 26.0.50; cl-progv: strange scoping due to implementation

From: Roland Winkler <[email-masked]>
Date: Thu, 13 Jul 2017 09:40:27 -0500

On Wed, Jul 12 2017, [email-masked] wrote:
>>> > Why does the lambda still refer to the lexical binding?
>>>
>>> Maybe it would be more obvious if we wrote it like this:
>>>
>>>     (let ((x 0))
>>>       (cl-progv (list (intern (read-string "Enter var: "))) (list 1)
>>>         (funcall (lambda () x))))
>>>
>>> Clearly the inner x must refer to the lexical let-binding, right?  Even
>>> if the user happens to enter `x' at the prompt this remains true.
>>
>> Not an argument per se, because with lexical binding mode off, you can
>> surely do that.
>
> Of course, if `x' is a dynamic variable (e.g., if you use (defvar x) or
> you don't have lexical binding enabled) then the inner x refers to the
> dynamic binding (again, regardless of what the user enters at the
> prompt).

I am not sure I can follow this thread:

The docstring of cl-progv says

  Bind SYMBOLS to VALUES dynamically in BODY.

But I am not sure whether this statement correctly reflects the actual
code of cl-progv: cl-progv evaluates a let form at runtime, but it is
not up to cl-progv to ensure dynamical binding.  I believe it depends on
whether lexical binding is on or off whether the code currently used by
cl-progv uses dynamical binding or lexical binding.

So it is my ignorant guess that a consistent behavior of cl-progv with
lexical binding on or off requires that the bindings of SYMBOLS to
VALUES is also passed to `eval' as a second arg.  From the docstring of eval:

  LEXICAL can also be an actual lexical environment, in the form of an
  alist mapping symbols to their value.