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

From: Mattias Engdegård <[email-masked]>
Date: Wed, 1 Dec 2021 23:32:49 +0100

1 dec. 2021 kl. 19.34 skrev Stefan Monnier <[email-masked]>:

>>> BTW, have you checked the impact on byte-code quality?
>> With respect to these patches?
> 
> No I meant w.r.t removing `let*` (or `let` as the case may be).

Yes, and I can confirm that both transformations (let* -> let and the inverse) seem to generate almost or exactly identical bytecode for lexbind code. If you can find an example where it's worse, I'd like to know.

>>> Also, If mapping is of the form (car-safe SYMBOL) is `var` really the
>>> correct answer?  Shouldn't it still be (cadr mapping)?
>> Can there ever be a difference?
> 
> There's a big philosophical difference, yes.

We could declare it an invariant and add an assertion.

> I think another way to do the patch B would be to replace `var` with
> `lifted` right when we construct the (apply-partially ...) thingy
> (i.e. in the :lambda-candidate part of the function), so those vars that
> get remapped to `internal-get-closed-var` wouldn't even make their way
> to `extend`.

Yes, that would probably be even cleaner. Then we wouldn't need to worry about shadowing for those.
I'm not going to do more experimenting with it now but do try it if it makes the code better.

By the way, I did try constant-propagating `(internal-get-closed-var N)` but got less yield than I hoped for. I'll look closer, maybe I made a silly mistake.

>> Good comments, thank you very much!
> 
> [ I resent this implicit suggestion that I could ever write something less
>  than a good comment.  ]

That wasn't for your consumption but to inform the unwashed masses who can't tell the difference!