From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.bugs Subject: bug#51982: Erroneous handling of local variables in byte-compiled nested lambdas Date: Tue, 30 Nov 2021 18:01:59 +0100 Message-ID: References: <87y25jo2q1.fsf@web.de> <29C3A3F8-CD9F-4AF2-A731-3304FC30E380@acm.org> <87wnl23pnd.fsf@web.de> <59A729EF-C4D4-47EB-9ADC-19FE8EBE7F10@acm.org> <877dd0bi17.fsf@web.de> Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.21\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_50889DC4-EA40-47C0-8963-0A04145B17E7" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="4815"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Michael Heerdegen , Paul Pogonyshev , 51982@debbugs.gnu.org To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Nov 30 18:04:26 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ms6YK-0000tW-Ix for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 30 Nov 2021 18:04:24 +0100 Original-Received: from localhost ([::1]:45848 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ms6YI-0001l2-LX for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 30 Nov 2021 12:04:22 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:54464) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ms6X1-0000Eh-A4 for bug-gnu-emacs@gnu.org; Tue, 30 Nov 2021 12:03:03 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:58966) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ms6X1-0007j6-1u for bug-gnu-emacs@gnu.org; Tue, 30 Nov 2021 12:03:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ms6X0-0004Ic-VS for bug-gnu-emacs@gnu.org; Tue, 30 Nov 2021 12:03:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 30 Nov 2021 17:03:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 51982 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 51982-submit@debbugs.gnu.org id=B51982.163829172716432 (code B ref 51982); Tue, 30 Nov 2021 17:03:02 +0000 Original-Received: (at 51982) by debbugs.gnu.org; 30 Nov 2021 17:02:07 +0000 Original-Received: from localhost ([127.0.0.1]:42275 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ms6W7-0004Gy-82 for submit@debbugs.gnu.org; Tue, 30 Nov 2021 12:02:07 -0500 Original-Received: from mail204c50.megamailservers.eu ([91.136.10.214]:43162 helo=mail193c50.megamailservers.eu) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ms6W4-0004Gl-UX for 51982@debbugs.gnu.org; Tue, 30 Nov 2021 12:02:06 -0500 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1638291722; bh=0seGn+0F4vzzaDd7XFe7H71PayTjUzjB3DvIgFbsOlo=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=M4XdyEyHwna5fTx1jD3JOVb0C/9SUa/OYoWrSRt+walJRKTYuwnmE7xojV0EbkqNQ +t0nMowau8ATCoC6m52EKrJBPotcc7aMMhbWWUnP5OEIoefAZLbxnXvzSINq11JoYN 9CjQacG2jZD9D1xT4g4l1V+3k0Xdi9J9SuSu+Z5M= Feedback-ID: mattiase@acm.or Original-Received: from stanniol.lan (c-b952e353.032-75-73746f71.bbcust.telenor.se [83.227.82.185]) (authenticated bits=0) by mail193c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 1AUH1xgq003746; Tue, 30 Nov 2021 17:02:01 +0000 In-Reply-To: X-Mailer: Apple Mail (2.3445.104.21) X-CTCH-RefID: str=0001.0A742F20.61A6590A.009D, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CTCH-VOD: Unknown X-CTCH-Spam: Unknown X-CTCH-Score: 0.000 X-CTCH-Flags: 0 X-CTCH-ScoreCust: 0.000 X-CSC: 0 X-CHA: v=2.4 cv=LIkF/La9 c=1 sm=1 tr=0 ts=61a6590a a=von4qPfY+hyqc0zmWf0tYQ==:117 a=von4qPfY+hyqc0zmWf0tYQ==:17 a=M51BFTxLslgA:10 a=iRZporoAAAAA:8 a=fYCMnBSh4KlL48zEYLcA:9 a=QEXdDO2ut3YA:10 a=QG20O0T1PFPAM2fPWDIA:9 a=B2y7HmGcmWMA:10 a=ZWWpVlJt-r_wLoX5z1kA:9 a=NOBgFS-JBQ2l-kSd6-zu:22 X-Origin-Country: SE X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:221149 Archived-At: --Apple-Mail=_50889DC4-EA40-47C0-8963-0A04145B17E7 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 30 nov. 2021 kl. 15.12 skrev Stefan Monnier : > Can we avoid this duplication by moving that code to a separate = function? I extracted a big part of the code into a common function but left the = free variable access and mutation outside. (Really want to get rid of = `let*`!) > These two tests are identical aren't they? No, they exercise different code paths (let and let*). > Also, can we change the > (setq x x) into something like (setq x (list x x)) and avoid using the > same `b` value for both `x` vars, so as to catch more potential = errors? Yes, thank you, it was an editing mistake. Fixed. > Looks good (better than patch A). And here I was prepared to apply patch A since it's slightly more = conservative and it seems to be a rare problem anyway. I've now split the patches in a more sensible (and easily reviewed) way: = the first corresponds to patch A, and the second is the diff to B. Take = a second look before making up your mind. > You say "On the other hand, patch B does abuse the cconv data = structures > a little (but it works!)" so the code should say something about > this abuse. A least I failed to see where the abuse lies. There are comments and doc strings such as EXTEND is a list of variables which might need to be accessed even = from places where they are shadowed, because some part of ENV causes them to be = used at places where they originally did not directly appear. but with the B patch we put things into `extend` that are not strictly = variables but (international-get-closed-var N). Similarly, `env` has entries like (VAR . (apply-partially F ARG1 ARG2 = ..)) where the ARGi are always treated as variables but now they can be = access forms as well. I suppose it doesn't matter much. There is an assertion at the very top = of `cconv-convert` which compares the elements by `eq` but it seems to = work all right... Thanks for the review =E2=80=93 new patches attached. --Apple-Mail=_50889DC4-EA40-47C0-8963-0A04145B17E7 Content-Disposition: attachment; filename=0001-Fix-closure-conversion-of-shadowed-captured-lambda-l.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Fix-closure-conversion-of-shadowed-captured-lambda-l.patch" Content-Transfer-Encoding: quoted-printable =46rom=20b56b04ac23f74dddd4648c9f86c8cf7423f70829=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Mon,=2022=20Nov=202021=2016:56:38=20+0100=0A= Subject:=20[PATCH=201/2]=20Fix=20closure-conversion=20of=20shadowed=20= captured=20lambda-lifted=0A=20vars=0A=0A*=20lisp/emacs-lisp/cconv.el=20= (cconv--lifted-arg):=20New.=0A(cconv-convert):=0ALambda=20lifted=20= variables=20(ones=20passed=20explicitly=20to=20lambda-lifted=0A= functions)=20that=20are=20also=20captured=20in=20an=20outer=20closure=20= and=20shadowed=0Awere=20renamed=20incorrectly.=20=20Fix=20that=20by=20= providing=20the=20correct=0Adefiniens=20for=20the=20closed-over=20= variable=20(bug#51982).=0A=0A*=20test/lisp/emacs-lisp/bytecomp-tests.el=20= (bytecomp-tests--test-cases):=0A*=20test/lisp/emacs-lisp/cconv-tests.el=20= (cconv-tests--intern-all)=0A(cconv-closure-convert-remap-var):=20Add=20= tests.=0A---=0A=20lisp/emacs-lisp/cconv.el=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20|=20=2028=20++++-=0A=20= test/lisp/emacs-lisp/bytecomp-tests.el=20|=20=2041=20+++++++=0A=20= test/lisp/emacs-lisp/cconv-tests.el=20=20=20=20|=20152=20= +++++++++++++++++++++++++=0A=203=20files=20changed,=20215=20= insertions(+),=206=20deletions(-)=0A=0Adiff=20--git=20= a/lisp/emacs-lisp/cconv.el=20b/lisp/emacs-lisp/cconv.el=0Aindex=20= 03e109f250..9808547b84=20100644=0A---=20a/lisp/emacs-lisp/cconv.el=0A+++=20= b/lisp/emacs-lisp/cconv.el=0A@@=20-304,6=20+304,22=20@@=20= cconv--convert-funcbody=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= `(,@(nreverse=20special-forms)=20,@(macroexp-unprogn=20body))))=0A=20=20=20= =20=20=20=20funcbody)))=0A=20=0A+(defun=20cconv--lifted-arg=20(var=20= env)=0A+=20=20"The=20argument=20to=20use=20for=20VAR=20in=20=CE=BB-lifted=20= calls=20according=20to=20ENV."=0A+=20=20(let=20((mapping=20(cdr=20(assq=20= var=20env))))=0A+=20=20=20=20(pcase-exhaustive=20mapping=0A+=20=20=20=20=20= =20(`(internal-get-closed-var=20.=20,_)=0A+=20=20=20=20=20=20=20;;=20The=20= variable=20is=20captured.=0A+=20=20=20=20=20=20=20mapping)=0A+=20=20=20=20= =20=20(`(car-safe=20(internal-get-closed-var=20.=20,_))=0A+=20=20=20=20=20= =20=20;;=20The=20variable=20is=20mutably=20captured;=20skip=0A+=20=20=20=20= =20=20=20;;=20the=20indirection=20step=20because=20the=20variable=20is=0A= +=20=20=20=20=20=20=20;;=20passed=20"by=20reference"=20to=20the=20= =CE=BB-lifted=20function.=0A+=20=20=20=20=20=20=20(cadr=20mapping))=0A+=20= =20=20=20=20=20((or=20'()=20`(car-safe=20,(pred=20symbolp)))=0A+=20=20=20= =20=20=20=20;;=20The=20variable=20is=20not=20captured;=20use=20the=20= (shadowed)=20variable=20value.=0A+=20=20=20=20=20=20=20var))))=0A+=0A=20= (defun=20cconv-convert=20(form=20env=20extend)=0A=20=20=20;;=20This=20= function=20actually=20rewrites=20the=20tree.=0A=20=20=20"Return=20FORM=20= with=20all=20its=20lambdas=20changed=20so=20they=20are=20closed.=0A@@=20= -428,10=20+444,11=20@@=20cconv-convert=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20= shadowed,=20so=20add=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20;;=20a=20reference=20to=20the=20outside=20binding=20and=20arrange=20= to=20use=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= that=20reference.=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((closedsym=20(make-symbol=20(format=20"closed-%s"=20var))))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((var-def=20= (cconv--lifted-arg=20var=20env))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(closedsym=20(make-symbol=20(format=20= "closed-%s"=20var))))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(setq=20new-env=20(cconv--remap-llv=20new-env=20var=20= closedsym))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20new-extend=20(cons=20closedsym=20(remq=20var=20new-extend)))=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20= `(,closedsym=20,var)=20binders-new)))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(push=20`(,closedsym=20,var-def)=20= binders-new)))=0A=20=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;;=20We=20push=20the=20element=20after=20redefined=20free=20variables=20= are=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20processed.=20=20= This=20is=20important=20to=20avoid=20the=20bug=20when=20free=0A@@=20= -449,14=20+466,13=20@@=20cconv-convert=0A=20=20=20=20=20=20=20=20=20=20= ;;=20before=20we=20know=20that=20the=20var=20will=20be=20in=20= `new-extend'=20(bug#24171).=0A=20=20=20=20=20=20=20=20=20=20(dolist=20= (binder=20binders-new)=0A=20=20=20=20=20=20=20=20=20=20=20=20(when=20= (memq=20(car-safe=20binder)=20new-extend)=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20shadowed,=20= so=20add=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20a=20reference=20= to=20the=20outside=20binding=20and=20arrange=20to=20use=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20;;=20that=20reference.=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20= shadowed.=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((var=20= (car-safe=20binder))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(var-def=20(cconv--lifted-arg=20var=20env))=0A=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(closedsym=20(make-symbol=20= (format=20"closed-%s"=20var))))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(setq=20new-env=20(cconv--remap-llv=20new-env=20var=20= closedsym))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= new-extend=20(cons=20closedsym=20(remq=20var=20new-extend)))=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(push=20`(,closedsym=20,var)=20= binders-new)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20= `(,closedsym=20,var-def)=20binders-new)))))=0A=20=0A=20=20=20=20=20=20=20= =20`(,letsym=20,(nreverse=20binders-new)=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20.=20,(mapcar=20(lambda=20(form)=0Adiff=20--git=20= a/test/lisp/emacs-lisp/bytecomp-tests.el=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0Aindex=20= 816f14a18d..a75a33b2dc=20100644=0A---=20= a/test/lisp/emacs-lisp/bytecomp-tests.el=0A+++=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0A@@=20-643,6=20+643,47=20@@=20= bytecomp-tests--test-cases=0A=20=0A=20=20=20=20=20(cond)=0A=20=20=20=20=20= (mapcar=20(lambda=20(x)=20(cond=20((=3D=20x=200))))=20'(0=201))=0A+=0A+=20= =20=20=20;;=20These=20expressions=20give=20different=20results=20in=20= lexbind=20and=20dynbind=20modes,=0A+=20=20=20=20;;=20but=20in=20each=20= the=20compiler=20and=20interpreter=20should=20agree!=0A+=20=20=20=20(let=20= ((f=20(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (lambda=20()=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20= ((g=20(lambda=20()=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let=20((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(list=20x=20(funcall=20g))))))))=0A+=20=20=20=20=20=20= (funcall=20(funcall=20f=20'b)))=0A+=20=20=20=20(let=20((f=20(lambda=20= (x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(lambda=20()=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((g=20(lambda=20()=20= x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20= ((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(list=20x=20(funcall=20g))))))))=0A+=20=20=20=20=20=20(funcall=20= (funcall=20f=20'b)))=0A+=20=20=20=20(let=20((f=20(lambda=20(x)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(lambda=20()=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(let=20((g=20(lambda=20()=20x)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20x=20(list=20x=20= x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20= ((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(list=20x=20(funcall=20g))))))))=0A+=20=20=20=20=20=20(funcall=20= (funcall=20f=20'b)))=0A+=20=20=20=20(let=20((f=20(lambda=20(x)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(lambda=20()=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(let=20((g=20(lambda=20()=20x)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20x=20(list=20x=20= x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20= ((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(list=20x=20(funcall=20g))))))))=0A+=20=20=20=20=20=20(funcall=20= (funcall=20f=20'b)))=0A+=20=20=20=20(let=20((f=20(lambda=20(x)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let=20((g=20(lambda=20()=20x))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(h=20(lambda=20= ()=20(setq=20x=20(list=20x=20x)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(list=20x=20(funcall=20g)=20(funcall=20h)))))))=0A+=20=20= =20=20=20=20(funcall=20(funcall=20f=20'b)))=0A+=20=20=20=20(let=20((f=20= (lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((g=20= (lambda=20()=20x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(h=20(lambda=20()=20(setq=20x=20(list=20x=20x)))))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((x=20'a))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20= g)=20(funcall=20h)))))))=0A+=20=20=20=20=20=20(funcall=20(funcall=20f=20= 'b)))=0A=20=20=20=20=20)=0A=20=20=20"List=20of=20expressions=20for=20= cross-testing=20interpreted=20and=20compiled=20code.")=0A=20=0Adiff=20= --git=20a/test/lisp/emacs-lisp/cconv-tests.el=20= b/test/lisp/emacs-lisp/cconv-tests.el=0Aindex=204290571735..0701892b8c=20= 100644=0A---=20a/test/lisp/emacs-lisp/cconv-tests.el=0A+++=20= b/test/lisp/emacs-lisp/cconv-tests.el=0A@@=20-205,5=20+205,157=20@@=20= cconv-convert-lambda-lifted=0A=20=20=20=20=20=20=20=20=20=20=20=20nil=20= 99)=0A=20=20=20=20=20=20=20=20=20=20=2042)))=0A=20=0A+(defun=20= cconv-tests--intern-all=20(x)=0A+=20=20"Intern=20all=20symbols=20in=20= X."=0A+=20=20(cond=20((symbolp=20x)=20(intern=20(symbol-name=20x)))=0A+=20= =20=20=20=20=20=20=20((consp=20x)=20(cons=20(cconv-tests--intern-all=20= (car=20x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(cconv-tests--intern-all=20(cdr=20x))))=0A+=20=20=20=20=20= =20=20=20;;=20Assume=20we=20don't=20need=20to=20deal=20with=20vectors=20= etc.=0A+=20=20=20=20=20=20=20=20(t=20x)))=0A+=0A+(ert-deftest=20= cconv-closure-convert-remap-var=20()=0A+=20=20;;=20Verify=20that=20we=20= correctly=20remap=20shadowed=20lambda-lifted=20variables.=0A+=0A+=20=20= ;;=20We=20intern=20all=20symbols=20for=20ease=20of=20comparison;=20this=20= works=20because=0A+=20=20;;=20the=20`cconv-closure-convert'=20result=20= should=20contain=20no=20pair=20of=0A+=20=20;;=20distinct=20symbols=20= having=20the=20same=20name.=0A+=0A+=20=20;;=20Sanity=20check:=20captured=20= variable,=20no=20lambda-lifting=20or=20shadowing:=0A+=20=20(should=20= (equal=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20'#'(lambda=20= (x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20#'(lambda=20()=20= x))))=0A+=20=20=20=20=20=20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(internal-make-closure=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20nil=20(x)=20nil=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(internal-get-closed-var=200)))))=0A= +=0A+=20=20;;=20Basic=20case:=0A+=20=20(should=20(equal=20= (cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let=20((f=20#'(lambda=20()=20x)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(let=20((x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f)))))))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((f=20= #'(lambda=20(x)=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let=20((x=20'b)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(closed-x=20= x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(list=20x=20(funcall=20f=20closed-x)))))))=0A+=20=20(should=20= (equal=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((f=20#'(lambda=20()=20= x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let*=20((x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20= f)))))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let=20((f=20#'(lambda=20(x)=20x)))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((closed-x=20x)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20= closed-x)))))))=0A+=0A+=20=20;;=20With=20the=20lambda-lifted=20shadowed=20= variable=20also=20being=20captured:=0A+=20=20(should=20(equal=0A+=20=20=20= =20=20=20=20=20=20=20=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20=20= =20=20=20=20=20(cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20#'(lambda=20()=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((f=20#'(lambda=20()=20x)))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20'a))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (list=20x=20(funcall=20f))))))))=0A+=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (internal-make-closure=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20nil=20(x)=20nil=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((f=20#'(lambda=20(x)=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((x=20'a)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(closed-x=20= (internal-get-closed-var=200)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20closed-x))))))))=0A+=20= =20(should=20(equal=0A+=20=20=20=20=20=20=20=20=20=20=20= (cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= #'(lambda=20()=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((f=20#'(lambda=20()=20x)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((x=20'a))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (list=20x=20(funcall=20f))))))))=0A+=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (internal-make-closure=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20nil=20(x)=20nil=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((f=20#'(lambda=20(x)=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let*=20((closed-x=20(internal-get-closed-var=200))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(list=20x=20(funcall=20f=20closed-x))))))))=0A+=20=20;;=20With=20= lambda-lifted=20shadowed=20variable=20also=20being=20mutably=20captured:=0A= +=20=20(should=20(equal=0A+=20=20=20=20=20=20=20=20=20=20=20= (cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= #'(lambda=20()=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((f=20#'(lambda=20()=20x)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20x=20x)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20= 'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(list=20x=20(funcall=20f))))))))=0A+=20=20=20=20=20=20=20=20=20= =20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((x=20(list=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(internal-make-closure=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20nil=20(x)=20nil=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20(car-safe=20x))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setcar=20= (internal-get-closed-var=200)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(car-safe=20= (internal-get-closed-var=200)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let=20((x=20'a)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(closed-x=20= (internal-get-closed-var=200)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20= closed-x)))))))))=0A+=20=20(should=20(equal=0A+=20=20=20=20=20=20=20=20=20= =20=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= #'(lambda=20()=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((f=20#'(lambda=20()=20x)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20x=20x)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((x=20= 'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(list=20x=20(funcall=20f))))))))=0A+=20=20=20=20=20=20=20=20=20= =20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((x=20(list=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(internal-make-closure=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20nil=20(x)=20nil=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20(car-safe=20x))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setcar=20= (internal-get-closed-var=200)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(car-safe=20= (internal-get-closed-var=200)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let*=20((closed-x=20(internal-get-closed-var=20= 0))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20closed-x)))))))))=0A= +=20=20;;=20Lambda-lifted=20variable=20that=20isn't=20actually=20= captured=20where=20it=20is=20shadowed:=0A+=20=20(should=20(equal=0A+=20=20= =20=20=20=20=20=20=20=20=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20= =20=20=20=20=20=20(cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((g=20#'(lambda=20()=20x))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(h=20#'(lambda=20()=20(setq=20= x=20x))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(list=20x=20(funcall=20g)=20(funcall=20h)))))))=0A+=20=20=20=20= =20=20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((x=20(list=20x)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let=20((g=20#'(lambda=20(x)=20(car-safe=20x)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (h=20#'(lambda=20(x)=20(setcar=20x=20(car-safe=20x)))))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20'b)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (closed-x=20x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(list=20x=20(funcall=20g=20closed-x)=20(funcall=20h=20= closed-x))))))))=0A+=20=20(should=20(equal=0A+=20=20=20=20=20=20=20=20=20= =20=20(cconv-tests--intern-all=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= '#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((g=20#'(lambda=20()=20x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(h=20#'(lambda=20()=20(setq=20x=20= x))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let*=20((x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(list=20x=20(funcall=20g)=20(funcall=20h)))))))=0A+=20=20=20= =20=20=20=20=20=20=20=20'#'(lambda=20(x)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(let=20((x=20(list=20x)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(let=20((g=20#'(lambda=20(x)=20(car-safe=20= x)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(h=20#'(lambda=20(x)=20(setcar=20x=20(car-safe=20x)))))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((closed-x=20= x)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(x=20'b))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(list=20x=20(funcall=20g=20closed-x)=20(funcall=20h=20= closed-x))))))))=0A+=20=20)=0A+=0A=20(provide=20'cconv-tests)=0A=20;;;=20= cconv-tests.el=20ends=20here=0A--=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_50889DC4-EA40-47C0-8963-0A04145B17E7 Content-Disposition: attachment; filename=0002-Improved-closure-conversion-of-shadowed-captured-lam.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0002-Improved-closure-conversion-of-shadowed-captured-lam.patch" Content-Transfer-Encoding: quoted-printable =46rom=20e93f3f44cc31a47e54c301157ce91f1b4d79e57e=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Mon,=2022=20Nov=202021=2016:56:38=20+0100=0A= Subject:=20[PATCH=202/2]=20Improved=20closure-conversion=20of=20shadowed=20= captured=0A=20lambda-lifted=20vars=0A=0A*=20lisp/emacs-lisp/cconv.el=20= (cconv-convert):=0AEliminate=20the=20intermediate=20variable=20= `closed-VAR`=20when=20the=20shadowed=0Avariable=20is=20captured=20in=20= an=20outer=20closure,=20since=20the=20accessor=20can=20be=0Aused=20= directly=20(bug#51982).=0A=0A*=20test/lisp/emacs-lisp/cconv-tests.el=20= (cconv-tests--intern-all)=0A(cconv-closure-convert-remap-var):=20Adapt=20= tests.=0A---=0A=20lisp/emacs-lisp/cconv.el=20=20=20=20=20=20=20=20=20=20=20= =20|=2033=20++++++++++++++++-------------=0A=20= test/lisp/emacs-lisp/cconv-tests.el=20|=2020=20+++++++----------=0A=202=20= files=20changed,=2026=20insertions(+),=2027=20deletions(-)=0A=0Adiff=20= --git=20a/lisp/emacs-lisp/cconv.el=20b/lisp/emacs-lisp/cconv.el=0Aindex=20= 9808547b84..a50aab93f2=20100644=0A---=20a/lisp/emacs-lisp/cconv.el=0A+++=20= b/lisp/emacs-lisp/cconv.el=0A@@=20-317,8=20+317,9=20@@=20= cconv--lifted-arg=0A=20=20=20=20=20=20=20=20;;=20passed=20"by=20= reference"=20to=20the=20=CE=BB-lifted=20function.=0A=20=20=20=20=20=20=20= =20(cadr=20mapping))=0A=20=20=20=20=20=20=20((or=20'()=20`(car-safe=20= ,(pred=20symbolp)))=0A-=20=20=20=20=20=20=20;;=20The=20variable=20is=20= not=20captured;=20use=20the=20(shadowed)=20variable=20value.=0A-=20=20=20= =20=20=20=20var))))=0A+=20=20=20=20=20=20=20;;=20The=20variable=20is=20= not=20captured.=20=20Add=20a=20reference=20to=20the=0A+=20=20=20=20=20=20= =20;;=20outside=20binding=20and=20arrange=20to=20use=20that=20reference.=0A= +=20=20=20=20=20=20=20(make-symbol=20(format=20"closed-%s"=20var))))))=0A= =20=0A=20(defun=20cconv-convert=20(form=20env=20extend)=0A=20=20=20;;=20= This=20function=20actually=20rewrites=20the=20tree.=0A@@=20-441,14=20= +442,16=20@@=20cconv-convert=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(cconv-convert=20value=20env=20extend)))))=0A= =20=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(when=20(and=20(eq=20= letsym=20'let*)=20(memq=20var=20new-extend))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20= shadowed,=20so=20add=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;;=20a=20reference=20to=20the=20outside=20binding=20and=20arrange=20to=20= use=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20that=20= reference.=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20= ((var-def=20(cconv--lifted-arg=20var=20env))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(closedsym=20(make-symbol=20= (format=20"closed-%s"=20var))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(setq=20new-env=20(cconv--remap-llv=20new-env=20var=20= closedsym))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20new-extend=20(cons=20closedsym=20(remq=20var=20new-extend)))=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20= `(,closedsym=20,var-def)=20binders-new)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20= shadowed;=20if=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= necessary,=20add=20a=20reference=20to=20the=20outside=20binding=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20and=20arrange=20to=20= use=20that=20reference.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(let*=20((lifted-arg=20(cconv--lifted-arg=20var=20env)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20This=20means=20that=20= we=20may=20add=20accessors=20to=20ENV=20and=20EXTEND=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20passing=20them=20off=20as=20= variables,=20but=20it's=20close=20enough.=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(setq=20new-env=20(cconv--remap-llv=20new-env=20= var=20lifted-arg))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(setq=20new-extend=20(cons=20lifted-arg=20(remq=20var=20= new-extend)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (when=20(symbolp=20lifted-arg)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(push=20`(,lifted-arg=20,var)=20binders-new))))=0A= =20=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20We=20push=20= the=20element=20after=20redefined=20free=20variables=20are=0A=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20;;=20processed.=20=20This=20is=20= important=20to=20avoid=20the=20bug=20when=20free=0A@@=20-468,11=20= +471,11=20@@=20cconv-convert=0A=20=20=20=20=20=20=20=20=20=20=20=20(when=20= (memq=20(car-safe=20binder)=20new-extend)=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20;;=20One=20of=20the=20lambda-lifted=20vars=20is=20shadowed.=0A= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20((var=20(car-safe=20= binder))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (var-def=20(cconv--lifted-arg=20var=20env))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(closedsym=20(make-symbol=20(format=20= "closed-%s"=20var))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20new-env=20(cconv--remap-llv=20new-env=20var=20closedsym))=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20new-extend=20(cons=20= closedsym=20(remq=20var=20new-extend)))=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(push=20`(,closedsym=20,var-def)=20binders-new)))))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(lifted-arg=20= (cconv--lifted-arg=20var=20env)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(setq=20new-env=20(cconv--remap-llv=20new-env=20var=20= lifted-arg))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= new-extend=20(cons=20lifted-arg=20(remq=20var=20new-extend)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(when=20(symbolp=20lifted-arg)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20`(,lifted-arg=20= ,var)=20binders-new))))))=0A=20=0A=20=20=20=20=20=20=20=20`(,letsym=20= ,(nreverse=20binders-new)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20.=20,(mapcar=20(lambda=20(form)=0Adiff=20--git=20= a/test/lisp/emacs-lisp/cconv-tests.el=20= b/test/lisp/emacs-lisp/cconv-tests.el=0Aindex=200701892b8c..3bd34e08d3=20= 100644=0A---=20a/test/lisp/emacs-lisp/cconv-tests.el=0A+++=20= b/test/lisp/emacs-lisp/cconv-tests.el=0A@@=20-267,9=20+267,8=20@@=20= cconv-closure-convert-remap-var=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(internal-make-closure=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20nil=20(x)=20nil=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20x)))=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20'a)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(closed-x=20= (internal-get-closed-var=200)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20closed-x))))))))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20'a))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(list=20= x=20(funcall=20f=20(internal-get-closed-var=200)))))))))=0A=20=20=20= (should=20(equal=0A=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-tests--intern-all=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= (cconv-closure-convert=0A@@=20-282,9=20+281,8=20@@=20= cconv-closure-convert-remap-var=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(internal-make-closure=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20nil=20(x)=20nil=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20x)))=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let*=20((closed-x=20= (internal-get-closed-var=200))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(x=20'a))=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20= closed-x))))))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(let*=20((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(list=20x=20(funcall=20f=20(internal-get-closed-var=20= 0)))))))))=0A=20=20=20;;=20With=20lambda-lifted=20shadowed=20variable=20= also=20being=20mutably=20captured:=0A=20=20=20(should=20(equal=0A=20=20=20= =20=20=20=20=20=20=20=20=20(cconv-tests--intern-all=0A@@=20-302,9=20= +300,8=20@@=20cconv-closure-convert-remap-var=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20= (car-safe=20x))))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(setcar=20(internal-get-closed-var=200)=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (car-safe=20(internal-get-closed-var=200)))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let=20((x=20'a)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(closed-x=20= (internal-get-closed-var=200)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20= closed-x)))))))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20= (internal-get-closed-var=200))))))))))=0A=20=20=20(should=20(equal=0A=20=20= =20=20=20=20=20=20=20=20=20=20(cconv-tests--intern-all=0A=20=20=20=20=20=20= =20=20=20=20=20=20=20(cconv-closure-convert=0A@@=20-321,9=20+318,8=20@@=20= cconv-closure-convert-remap-var=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((f=20#'(lambda=20(x)=20(car-safe=20x))))=0A=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setcar=20= (internal-get-closed-var=200)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(car-safe=20= (internal-get-closed-var=200)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let*=20((closed-x=20(internal-get-closed-var=20= 0))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(x=20'a))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(list=20x=20(funcall=20f=20closed-x)))))))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20= ((x=20'a))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(list=20x=20(funcall=20f=20(internal-get-closed-var=20= 0))))))))))=0A=20=20=20;;=20Lambda-lifted=20variable=20that=20isn't=20= actually=20captured=20where=20it=20is=20shadowed:=0A=20=20=20(should=20= (equal=0A=20=20=20=20=20=20=20=20=20=20=20=20(cconv-tests--intern-all=0A= --=20=0A2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_50889DC4-EA40-47C0-8963-0A04145B17E7--