From unknown Sat Jun 14 01:39:26 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#68938 <68938@debbugs.gnu.org> To: bug#68938 <68938@debbugs.gnu.org> Subject: Status: Emacs "master". Incorrect code generated by pcase. Reply-To: bug#68938 <68938@debbugs.gnu.org> Date: Sat, 14 Jun 2025 08:39:26 +0000 retitle 68938 Emacs "master". Incorrect code generated by pcase. reassign 68938 emacs submitter 68938 Alan Mackenzie severity 68938 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Mon Feb 05 12:19:22 2024 Received: (at submit) by debbugs.gnu.org; 5 Feb 2024 17:19:22 +0000 Received: from localhost ([127.0.0.1]:52218 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rX2cs-0008Q0-CM for submit@debbugs.gnu.org; Mon, 05 Feb 2024 12:19:22 -0500 Received: from lists.gnu.org ([2001:470:142::17]:32904) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rX2cr-0008Pm-AV for submit@debbugs.gnu.org; Mon, 05 Feb 2024 12:19:21 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rX2cZ-0006RO-Cf for bug-gnu-emacs@gnu.org; Mon, 05 Feb 2024 12:19:03 -0500 Received: from mail.muc.de ([193.149.48.3]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rX2cR-0004i2-A3 for bug-gnu-emacs@gnu.org; Mon, 05 Feb 2024 12:19:03 -0500 Received: (qmail 26334 invoked by uid 3782); 5 Feb 2024 18:18:40 +0100 Received: from acm.muc.de (pd953a84b.dip0.t-ipconnect.de [217.83.168.75]) (using STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP; Mon, 05 Feb 2024 18:18:40 +0100 Received: (qmail 8422 invoked by uid 1000); 5 Feb 2024 17:18:40 -0000 Date: Mon, 5 Feb 2024 17:18:40 +0000 To: bug-gnu-emacs@gnu.org Subject: Emacs "master". Incorrect code generated by pcase. Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-DEBBUGS-CC: Stefan Monnier X-Submission-Agent: TMDA/1.3.x (Ph3nix) From: Alan Mackenzie X-Primary-Address: acm@muc.de Received-SPF: pass client-ip=193.149.48.3; envelope-from=acm@muc.de; helo=mail.muc.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 0.9 (/) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.1 (/) Hello Stefan and Emacs. In a development version of Emacs, last synched with master in December, I have added the following pcase clause to macroexp--expand-all in lisp/emacs-lisp/macroexp.el: (`(,(and 'defalias d (guard (and (null defining-symbol) (symbol-with-pos-p d)))) ',sym . ,_) ;; Here, don't change the form; just set `defining-symbol' ;; for a (defalias 'foo ...) in the source code. ;; (when (symbol-with-pos-p d) (setq defining-symbol sym) form) .. pcase expands that clause to this cond clause: ((eq x0 'defalias) (cond ((let* ((d x0)) (and (null defining-symbol) (symbol-with-pos-p d))) (let* ((x14 (cdr-safe form))) (cond ((consp x14) (let* ((x15 (car-safe x14))) (cond ((consp x15) (let* ((x16 (car-safe x15))) (cond ((eq x16 'quote) (let* ((x17 (cdr-safe x15))) (cond ((consp x17) (let* ((x18 (car-safe x17)) (x19 (cdr-safe x17))) (cond ((null x19) (let ((d x0) (sym x18)) (ignore d) (setq defining-symbol sym) form)) ((consp x0) (let* ((x21 (car-safe x0))) (if (eq x21 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0))))) ((consp x0) (let* ((x23 (car-safe x0))) (if (eq x23 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0))))) ((consp x0) (let* ((x25 (car-safe x0))) (if (eq x25 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0))))) ((consp x0) (let* ((x27 (car-safe x0))) (if (eq x27 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0))))) ((consp x0) (let* ((x29 (car-safe x0))) (if (eq x29 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0))))) ((consp x0) (let* ((x31 (car-safe x0))) (if (eq x31 'lambda) (let* ((x33 (cdr-safe form))) (funcall pcase-3 x0 x33)) (funcall pcase-2 x0)))) (t (funcall pcase-2 x0)))) .. This contains errors: (i) Although it has been established that x0 is 'defalias, there are many tests (consp x0). (ii) There are calls of the form (funcall pcase-2 x0), i.e. (funcall pcase-2 'defalias). This causes a wrong-number-of-arguments error. (iii) There is no sign of the final `form' being returned, though this may be being done elsewhere. -- Alan Mackenzie (Nuremberg, Germany). From debbugs-submit-bounces@debbugs.gnu.org Mon Feb 05 13:27:47 2024 Received: (at 68938) by debbugs.gnu.org; 5 Feb 2024 18:27:47 +0000 Received: from localhost ([127.0.0.1]:52275 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rX3h5-0001lt-A1 for submit@debbugs.gnu.org; Mon, 05 Feb 2024 13:27:47 -0500 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:23279) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rX3h1-0001ld-Tj for 68938@debbugs.gnu.org; Mon, 05 Feb 2024 13:27:45 -0500 Received: from pmg1.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 83B5E100390; Mon, 5 Feb 2024 13:27:24 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1707157643; bh=hSTZVlyTI33KjXqwstWvn/WoaMY0VOZ6HxQ+5mKHRNg=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=ImSdSGhmPGekaQTlvAfyYJgWDRLKKl6Ja6ZvhEUU1/nRZMHJKVMLaRDxPrQAEUuTI y/xpahJAwizpgNJ/NGUsmmVo+pJFX42xNToazojnKRp9loPLwIsQc+c5eiQmJXhp6U CaJa7H5WuLcp0oduN26cz+I1r8ck5amA1cOxaO1m+yFVAqc1rXbavicYO7KVBnKM4H L1YYOGYfsaH3mXewa9Jc+ITZg9aU6WsSpKJ5YCBULA3d0ysILcwiMtey+mIrkhb/vb 96Oxy3ui3e3Q1Lus4KOdO6jUBut2wm4Ok2MfbuBvwGI9XoDN6qSdjzcbUgtOTXlV9X hH5BoNZdyV95g== Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 6472A1002B0; Mon, 5 Feb 2024 13:27:23 -0500 (EST) Received: from pastel (69-165-153-17.dsl.teksavvy.com [69.165.153.17]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 042031207A7; Mon, 5 Feb 2024 13:27:22 -0500 (EST) From: Stefan Monnier To: Alan Mackenzie Subject: Re: bug#68938: Emacs "master". Incorrect code generated by pcase. In-Reply-To: (Alan Mackenzie's message of "Mon, 5 Feb 2024 17:18:40 +0000") Message-ID: References: Date: Mon, 05 Feb 2024 13:27:21 -0500 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.310 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain T_SCC_BODY_TEXT_LINE -0.01 - X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 68938 Cc: 68938@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > In a development version of Emacs, last synched with master in December, > I have added the following pcase clause to macroexp--expand-all in > lisp/emacs-lisp/macroexp.el: > > (`(,(and 'defalias d > (guard (and (null defining-symbol) > (symbol-with-pos-p d)))) > ',sym . ,_) > ;; Here, don't change the form; just set `defining-symbol' > ;; for a (defalias 'foo ...) in the source code. > ;; (when (symbol-with-pos-p d) > (setq defining-symbol sym) > form) Where did do you add it? > .. pcase expands that clause to this cond clause: > > ((eq x0 'defalias) > (cond > ((let* ((d x0)) > (and (null defining-symbol) (symbol-with-pos-p d))) > (let* ((x14 (cdr-safe form))) > (cond > ((consp x14) > (let* ((x15 (car-safe x14))) > (cond > ((consp x15) > (let* ((x16 (car-safe x15))) > (cond > ((eq x16 'quote) > (let* ((x17 (cdr-safe x15))) > (cond > ((consp x17) > (let* ((x18 (car-safe x17)) (x19 (cdr-safe x17))) > (cond > ((null x19) > (let ((d x0) (sym x18)) > (ignore d) (setq defining-symbol sym) form)) > ((consp x0) > (let* ((x21 (car-safe x0))) > (if (eq x21 'lambda) (funcall pcase-3 x0 x14) > (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0))))) > ((consp x0) > (let* ((x23 (car-safe x0))) > (if (eq x23 'lambda) (funcall pcase-3 x0 x14) > (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0))))) > ((consp x0) > (let* ((x25 (car-safe x0))) > (if (eq x25 'lambda) (funcall pcase-3 x0 x14) > (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0))))) > ((consp x0) > (let* ((x27 (car-safe x0))) > (if (eq x27 'lambda) (funcall pcase-3 x0 x14) > (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0))))) > ((consp x0) > (let* ((x29 (car-safe x0))) > (if (eq x29 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0))))) > ((consp x0) > (let* ((x31 (car-safe x0))) > (if (eq x31 'lambda) > (let* ((x33 (cdr-safe form))) (funcall pcase-3 x0 x33)) > (funcall pcase-2 x0)))) > (t (funcall pcase-2 x0)))) > > .. This contains errors: > > (i) Although it has been established that x0 is 'defalias, there are many > tests (consp x0). Yup, clearly some missed optimization. I added your code just before the (`(function ,(and f `(lambda . ,_))) branch, and I didn't see such poor code, so it seems that it depends on further details. On further inspection I see a similar problem in another branch, where it generated: ((pcase--flip memq '(defconst defvar) x71) (let* ((x78 (cdr-safe form))) (cond ((consp x78) (let* ((x79 (car-safe x78))) (cond ((symbolp x79) (let ((name x79)) (push name macroexp--dynvars) (macroexp--all-forms form 2))) ((consp x71) (let* ((x81 (car-safe x71))) (if (eq x81 'lambda) (funcall pcase-2 x71 x78) (funcall pcase-1 x71)))) (t (funcall pcase-1 x71))))) ((consp x71) (let* ((x83 (car-safe x71))) (if (eq x83 'lambda) (funcall pcase-2 x71 x78) (funcall pcase-1 x71)))) (t (funcall pcase-1 x71))))) where we do that same useless (consp x71) test. I think this case is "normal" (the branch's test is basically (memq x71 '(defconst defvar), i.e. more complex than (eq x71 'defalias)) and I seem to remember consciously punting on handling such things in `pcase--mutually-exclusive-p`. Your case doesn't sound like one I'm aware of, OTOH. > (ii) There are calls of the form (funcall pcase-2 x0), i.e. (funcall > pcase-2 'defalias). This causes a wrong-number-of-arguments error. I don't see this problem here. In my case it's (funcall pcase-1 x71) but the number of arguments is right since pcase-1 is defined a bit earlier as: (lambda (func) (let ((handler (function-get func 'compiler-macro))) (if (null handler) (macroexp--all-forms form 1) (unless (functionp handler) (with-demoted-errors "macroexp--expand-all: %S" (autoload-do-load (indirect-function func) func))) (let ((newform (macroexp--compiler-macro handler form))) (if (eq form newform) (if (equal form (setq newform (macroexp--all-forms form 1))) form (setq form (macroexp--compiler-macro handler newform)) (if (eq newform form) newform (macroexp--expand-all form))) (macroexp--expand-all newform)))))) > (iii) There is no sign of the final `form' being returned, though this > may be being done elsewhere. I see the following in your code sample: (cond ((null x19) (let ((d x0) (sym x18)) (ignore d) (setq defining-symbol sym) form)) which seems to be correctly returning `form`. Stefan From debbugs-submit-bounces@debbugs.gnu.org Tue Feb 06 07:59:16 2024 Received: (at 68938) by debbugs.gnu.org; 6 Feb 2024 12:59:16 +0000 Received: from localhost ([127.0.0.1]:53391 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rXL2i-00074k-9S for submit@debbugs.gnu.org; Tue, 06 Feb 2024 07:59:16 -0500 Received: from mail.muc.de ([193.149.48.3]:24224) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rXL2f-00074P-VY for 68938@debbugs.gnu.org; Tue, 06 Feb 2024 07:59:14 -0500 Received: (qmail 31812 invoked by uid 3782); 6 Feb 2024 13:58:54 +0100 Received: from acm.muc.de (p4fe15bf0.dip0.t-ipconnect.de [79.225.91.240]) (using STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP; Tue, 06 Feb 2024 13:58:53 +0100 Received: (qmail 18446 invoked by uid 1000); 6 Feb 2024 12:58:53 -0000 Date: Tue, 6 Feb 2024 12:58:53 +0000 To: Stefan Monnier Subject: Re: bug#68938: Emacs "master". Incorrect code generated by pcase. Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Submission-Agent: TMDA/1.3.x (Ph3nix) From: Alan Mackenzie X-Primary-Address: acm@muc.de X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 68938 Cc: acm@muc.de, 68938@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello, Stefan. On Mon, Feb 05, 2024 at 13:27:21 -0500, Stefan Monnier wrote: > > In a development version of Emacs, last synched with master in December, > > I have added the following pcase clause to macroexp--expand-all in > > lisp/emacs-lisp/macroexp.el: > > (`(,(and 'defalias d > > (guard (and (null defining-symbol) > > (symbol-with-pos-p d)))) > > ',sym . ,_) > > ;; Here, don't change the form; just set `defining-symbol' > > ;; for a (defalias 'foo ...) in the source code. > > ;; (when (symbol-with-pos-p d) > > (setq defining-symbol sym) > > form) > Where did do you add it? Just before the (`(function ,(and f `(lambda . ,_))) clause, like you did. > > .. pcase expands that clause to this cond clause: > > ((eq x0 'defalias) > > (cond > > ((let* ((d x0)) > > (and (null defining-symbol) (symbol-with-pos-p d))) > > (let* ((x14 (cdr-safe form))) > > (cond > > ((consp x14) > > (let* ((x15 (car-safe x14))) > > (cond > > ((consp x15) > > (let* ((x16 (car-safe x15))) > > (cond > > ((eq x16 'quote) > > (let* ((x17 (cdr-safe x15))) > > (cond > > ((consp x17) > > (let* ((x18 (car-safe x17)) (x19 (cdr-safe x17))) > > (cond > > ((null x19) > > (let ((d x0) (sym x18)) > > (ignore d) (setq defining-symbol sym) form)) > > ((consp x0) > > (let* ((x21 (car-safe x0))) > > (if (eq x21 'lambda) (funcall pcase-3 x0 x14) > > (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0))))) > > ((consp x0) > > (let* ((x23 (car-safe x0))) > > (if (eq x23 'lambda) (funcall pcase-3 x0 x14) > > (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0))))) > > ((consp x0) > > (let* ((x25 (car-safe x0))) > > (if (eq x25 'lambda) (funcall pcase-3 x0 x14) > > (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0))))) > > ((consp x0) > > (let* ((x27 (car-safe x0))) > > (if (eq x27 'lambda) (funcall pcase-3 x0 x14) > > (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0))))) > > ((consp x0) > > (let* ((x29 (car-safe x0))) > > (if (eq x29 'lambda) (funcall pcase-3 x0 x14) (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0))))) > > ((consp x0) > > (let* ((x31 (car-safe x0))) > > (if (eq x31 'lambda) > > (let* ((x33 (cdr-safe form))) (funcall pcase-3 x0 x33)) > > (funcall pcase-2 x0)))) > > (t (funcall pcase-2 x0)))) > > > > .. This contains errors: > > > > (i) Although it has been established that x0 is 'defalias, there are many > > tests (consp x0). > Yup, clearly some missed optimization. > I added your code just before the > (`(function ,(and f `(lambda . ,_))) > branch, and I didn't see such poor code, so it seems that it depends on > further details. Yes. I think my bug report was premature at best. I was part way through amending backquote.el to be able to add the position information into things like the lambda in (push `(,bsym (lambda ,(mapcar #'car varvals) ,@ignores ,@code)) defs)) in pcase--expand. I think this bit of code deals with creating pcase-1, etc., so it seems highly likely my tentative changes were to blame. > On further inspection I see a similar problem in another branch, > where it generated: > ((pcase--flip memq '(defconst defvar) x71) > (let* ((x78 (cdr-safe form))) > (cond > ((consp x78) > (let* ((x79 (car-safe x78))) > (cond > ((symbolp x79) > (let ((name x79)) > (push name macroexp--dynvars) > (macroexp--all-forms form 2))) > ((consp x71) > (let* ((x81 (car-safe x71))) > (if (eq x81 'lambda) (funcall pcase-2 x71 x78) > (funcall pcase-1 x71)))) > (t (funcall pcase-1 x71))))) > ((consp x71) > (let* ((x83 (car-safe x71))) > (if (eq x83 'lambda) (funcall pcase-2 x71 x78) > (funcall pcase-1 x71)))) > (t (funcall pcase-1 x71))))) > where we do that same useless (consp x71) test. I think this case is > "normal" (the branch's test is basically (memq x71 '(defconst defvar), > i.e. more complex than (eq x71 'defalias)) and I seem to remember > consciously punting on handling such things in > `pcase--mutually-exclusive-p`. > Your case doesn't sound like one I'm aware of, OTOH. I think I should just close the bug as not a bug. It was one of these things I couldn't understand or do anything about, but right after reporting it, the solution became obvious, and I couldn't reproduce the bug easily any more. I've got my amendments to backquote.el working, now. > > (ii) There are calls of the form (funcall pcase-2 x0), i.e. (funcall > > pcase-2 'defalias). This causes a wrong-number-of-arguments error. > I don't see this problem here. In my case it's > (funcall pcase-1 x71) > but the number of arguments is right since pcase-1 is defined a bit > earlier as: > (lambda (func) > (let ((handler (function-get func 'compiler-macro))) > (if (null handler) (macroexp--all-forms form 1) > (unless (functionp handler) > (with-demoted-errors "macroexp--expand-all: %S" > (autoload-do-load (indirect-function func) func))) > (let ((newform (macroexp--compiler-macro handler form))) > (if (eq form newform) > (if > (equal form > (setq newform > (macroexp--all-forms form 1))) > form > (setq form > (macroexp--compiler-macro handler newform)) > (if (eq newform form) newform > (macroexp--expand-all form))) > (macroexp--expand-all newform)))))) > > (iii) There is no sign of the final `form' being returned, though this > > may be being done elsewhere. > I see the following in your code sample: > (cond > ((null x19) > (let ((d x0) (sym x18)) > (ignore d) (setq defining-symbol sym) form)) > which seems to be correctly returning `form`. Yes. Sorry about this bug report, which turned out to be a time waster. > Stefan -- Alan Mackenzie (Nuremberg, Germany).