Subject: bug#51982: Erroneous handling of local variables in byte-compiled nested lambdas

From: Paul Pogonyshev <[email-masked]>
Date: Sat, 20 Nov 2021 17:54:49 +0100

Just to note: I consider this bug pretty important. The example function
looks artificial, but I got the real failure by combining macros from
different packages (`dash.el' for all the `it' bindings, plus `pcase' and
`iter2' for lambdas, but I'm pretty sure you could get a failure with
nested complicated `pcase' alone, if you want to go "only built-in" route).
So, while it is apparently unlikely, you still can stumble into an
incomprehensible breakdown in any sofisticated function by nesting enough
macros that work otherwise and actually produce code that should work also
in this case. But doesn't, when byte-compiled.

Paul

On Sat, 20 Nov 2021 at 05:44, Michael Heerdegen <[email-masked]>
wrote:

> Hello Paul,
>
> thanks for the report, I can reproduce the issue, there is something
> going wrong when compiling.  I guess this is something for Mattias or
> Stefan maybe? (CC'd)
>
> #+begin_src emacs-lisp
> ; -*- lexical-binding: t -*-
>
> (defun wtf (x)
>   (let ((it 0))
>     #'(lambda ()
>         (let ((fn #'(lambda () it)))
>           (if x
>               (let ((it x))
>                 it)
>             (funcall fn))))))
> #+end_src
>
> Byte compile:
>
> >     wtf.el:9:17:Warning: reference to free variable ‘it’
>
> (funcall (wtf 1))
>
> >     Symbol’s value as variable is void: it
>
> while expected result is 1.  Uncompiled code works as expected.
>
> TIA,
>
> Michael.
>