GNU bug report logs - #80121
31.0.50; cond*/match* (or ...) patterns

Previous Next

Package: emacs;

Reported by: Richard Lawrence <rwl <at> recursewithless.net>

Date: Sat, 3 Jan 2026 09:43:01 UTC

Severity: normal

Found in version 31.0.50

To reply to this bug, email your comments to 80121 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#80121; Package emacs. (Sat, 03 Jan 2026 09:43:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Richard Lawrence <rwl <at> recursewithless.net>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sat, 03 Jan 2026 09:43:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Richard Lawrence <rwl <at> recursewithless.net>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; cond*/match* (or ...) patterns 
Date: Sat, 03 Jan 2026 10:41:31 +0100
I am experimenting with `cond*' and `match*' for the first time, and
think I've run into a bug in (or ...) subpatterns.

I have a list of tokens represented like this:

((:date ... :begin ... :end ...)
 (:time ... :begin ... :end ...)
 ...)

I want to match, e.g., the first two items on this list when one is a
date and the other is a time.  So I wrote:

(cond*
 ((match* (cdr-ignore (or (list (list :date d) (list :time t))
                          (list (list :time t) (list :date d))))
          tokens)
  (do-something d t)))

This works as expected: the `list' patterns expand to check that the car
of the inner list is :date or :time, and bind the corresponding
variables.  However, if I also try to match subsequent list elements in
the tokens, like

(cond*
 ((match* (cdr-ignore (or (list (list :date d :begin db)
                                (list :time t :begin tb))
                          (list (list :time t :begin tb)
                                (list :date d :begin db))))
          tokens)
  (do-something d t db tb)))

then this expands to:

(let ((d15675 tokens))
  (let (ba15678 ba15677 ba15676)
    (if (or (progn
              (setq ba15676 nil)
              (setq ba15677 nil)
              (setq ba15678 nil))
            (progn
              (setq ba15678 nil)
              (setq ba15676 nil)
              (setq ba15677 nil)))
        (let* ((d ba15676)
               (db ba15677)
               (tb ba15678))
          (do-something d t db tb))
      nil)))

which simply always returns nil.  I suspect the problem is in the
disjunction pattern handling in `cond*-subpat', where there is a comment
that says:

 ;; The main complexity is unsetting the pattern variables
 ;; that tentatively match in an or-branch that later failed.

The `progn' form which is setting all the bindings to nil is expanded
from `(progn ,@clearing) a little ways below that comment.  It looks to
me like this form is maybe missing a reference to `expression', or
perhaps should be part of a larger form that contains `expression'.  Or
am I misunderstanding something?

Thanks!  Here's the rest of the report-emacs-bug info:

In GNU Emacs 31.0.50 (build 12, x86_64-pc-linux-gnu, GTK+ Version
 3.24.38, cairo version 1.16.0) of 2025-12-22 built on ohm
Repository revision: b185d093e0feab89cdbcebb4a4bf74222144296b
Repository branch: scratch/icalendar
Windowing system distributor 'The X.Org Foundation', version 11.0.12201009
System Description: Debian GNU/Linux 12 (bookworm)

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND
SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINERAMA
XINPUT2 XPM XRANDR GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  recentf-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  server-mode: t
  override-global-mode: t
  global-evil-surround-mode: t
  evil-surround-mode: t
  evil-mode: t
  evil-local-mode: t
  ivy-mode: t
  electric-pair-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  minibuffer-nonselected-mode: t
  minibuffer-regexp-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/rwl/.emacs.d/elpa/magit-4.1.0/magit-autorevert hides /home/rwl/.emacs.d/elpa/magit-section-4.1.0/magit-autorevert
/home/rwl/.emacs.d/elpa/lua-mode-20231023.947/lua-mode hides /home/rwl/src/emacs/lisp/progmodes/lua-mode

Features:
(shadow emacsbug lisp-mnt smiley gnus-cite gnus-async gnus-bcklg
gnus-agent gnus-srvr gnus-score score-mode nnvirtual nntp gnus-ml
gnus-msg nndoc gnus-cache gnus-dup display-line-numbers debbugs-gnu
debbugs soap-client rng-xsd xsd-regexp debbugs-compat woman man pulse
descr-text propose-time calc-undo calc-misc whitespace network-stream
url-cache cond-star help-macro elfeed-link elfeed-show elfeed-search
elfeed-csv elfeed elfeed-curl elfeed-log xml-query elfeed-db elfeed-lib
gnus-icalendar-tests gnus-icalendar org-capture epa-file calc-alg
em-unix em-term term disp-table ehelp em-script em-prompt em-pred em-ls
em-hist em-glob em-extpipe em-cmpl em-dirs em-basic em-banner em-alias
esh-mode esh-var calc-arith calc-map calc-stat calc-vec calc-ext
calc-menu calc-aent calc calc-loaddefs calc-macs tex-mode cal-julian
lunar solar let-alist cc-mode cc-fonts cc-guess cc-menus cc-cmds
cc-styles cc-align cc-engine cc-vars cc-defs textsec uni-scripts
idna-mapping ucs-normalize uni-confusable textsec-check qp sort flyspell
orgalist magit-patch cus-edit cus-load texinfo texinfo-loaddefs ert-x
novice thai-util thai-word git-rebase icalendar-mode ol-eww eww vtable
url-queue mm-url ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect
gnus-art mm-uu mml2015 gnus-sum shr pixel-fill kinsoku url-file svg dom
gnus-group gnus-undo gnus-start gnus-dbus dbus gnus-cloud nnimap nnmail
mail-source utf7 nnoo gnus-spec gnus-int gnus-range gnus-win gnus
nnheader range ol-docview doc-view jka-compr image-mode exif ol-bibtex
bibtex ol-bbdb ol-w3m ol-doi org-link-doi tabify cal-move ledger-mode
ledger-check ledger-texi ledger-test ledger-sort ledger-report
ledger-reconcile ledger-occur ledger-fonts ledger-fontify ledger-state
ledger-complete ledger-schedule ledger-xact ledger-post ledger-exec
ledger-init ledger-navigate eshell esh-cmd esh-ext esh-proc esh-opt
esh-io esh-arg esh-module esh-module-loaddefs esh-util ledger-context
ledger-commodities ledger-regex cua-base cl-print copyright mm-archive
grep mule-util ert ewoc debug backtrace mail-extr dired-aux vc
magit-extras face-remap recentf tree-widget magit-bookmark bookmark
icalendar-macs tramp-sh shortdoc comp-common help-fns radix-tree
misearch multi-isearch vc-git vc-dispatcher bug-reference ffap
tramp-cache time-stamp tramp trampver tramp-integration files-x
tramp-message tramp-compat tramp-loaddefs warnings ediff ediff-merg
ediff-mult ediff-wind ediff-diff ediff-help ediff-init ediff-util
magit-submodule magit-blame magit-stash magit-reflog magit-bisect
magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit
magit-sequence magit-notes magit-worktree magit-tag magit-merge
magit-branch magit-reset magit-files magit-refs magit-status magit
magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff
smerge-mode diff git-commit log-edit pcvs-util add-log magit-core
magit-autorevert autorevert filenotify magit-margin magit-transient
magit-process with-editor server magit-mode transient benchmark
magit-git magit-base magit-section cursor-sensor dash two-column ob-R
ob-python python ob-shell shell org-caldav url-dav parse-time iso8601
url-http url-auth url-gw nsm xml ox-odt rng-loc rng-uri rng-parse
rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns nxml-enc xmltok
nxml-util ox-latex ox-icalendar ox-html table ox-ascii ox-publish ox
org-attach org-agenda org-element org-persist org-id avl-tree generator
org-refile ol-notmuch notmuch notmuch-tree notmuch-jump notmuch-hello
wid-edit notmuch-show notmuch-print notmuch-crypto notmuch-mua
notmuch-message notmuch-draft notmuch-maildir-fcc notmuch-address
notmuch-company notmuch-parser notmuch-wash diff-mode track-changes
coolj goto-addr notmuch-tag crm notmuch-lib notmuch-compat hl-line
message sendmail yank-media rfc822 mml mailabbrev mail-utils gmm-utils
mailheader mm-view mml-smime mml-sec gnus-util smime gnutls puny dig
mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util
ietf-drums mail-prsvr compat org ob ob-tangle ob-ref ob-lob ob-table
ob-exp org-macro org-src sh-script smie treesit executable ob-comint
org-pcomplete pcomplete org-list org-footnote org-faces org-entities
noutline outline org-version ob-emacs-lisp ob-core ob-eval org-cycle
org-table ol org-fold org-fold-core org-keys oc org-loaddefs find-func
org-compat use-package-bind-key bind-key easy-mmode evil-surround evil
evil-keybindings evil-integration evil-maps evil-commands reveal
evil-jumps evil-command-window evil-types evil-search evil-ex
evil-macros evil-repeat evil-states evil-core evil-common thingatpt rect
evil-vars edmacro kmacro diary-icalendar pp cal-dst icalendar-recur
icalendar-utils icalendar-parser time-date icalendar-ast org-element-ast
inline org-macs format-spec icalendar diary-lib diary-loaddefs skeleton
cal-menu calendar cal-loaddefs epa derived epg rfc6068 epg-config advice
counsel xref project dired dired-loaddefs compile text-property-search
comint ansi-osc ansi-color swiper ivy delsel ring ivy-faces ivy-overlay
colir elec-pair ispell rx solarized-dark-theme solarized-theme solarized
solarized-faces color cl-extra help-mode use-package-ensure
use-package-core finder-inf calfw-autoloads calfw-ical-autoloads
counsel-autoloads debbugs-autoloads elfeed-autoloads
evil-surround-autoloads evil-autoloads gnu-elpa-keyring-update-autoloads
goto-chg-autoloads howm-autoloads ledger-mode-autoloads
lua-mode-autoloads magit-autoloads pcase magit-section-autoloads
dash-autoloads markdown-mode-autoloads ol-notmuch-autoloads
notmuch-autoloads org-caldav-autoloads solarized-theme-autoloads
swiper-autoloads ivy-autoloads info with-editor-autoloads xr-autoloads
yaml-mode-autoloads package browse-url xdg url url-proxy url-privacy
url-expand url-methods url-history url-cookie generate-lisp-file
url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq
eieio eieio-core cl-macs icons password-cache json subr-x map byte-opt
gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl
tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd
touch-screen tool-bar dnd fontset image regexp-opt fringe tabulated-list
replace newcomment text-mode lisp-mode prog-mode register page tab-bar
menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse
jit-lock font-lock syntax font-core term/tty-colors frame minibuffer
nadvice seq simple cl-generic indonesian philippine cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european
ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop
case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify dynamic-setting system-font-setting
font-render-setting cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process tty-child-frames emacs)

Memory information:
((conses 16 2456394 674674) (symbols 48 64136 2)
 (strings 32 265404 32661) (string-bytes 1 65454423)
 (vectors 16 173126) (vector-slots 8 2444619 307649)
 (floats 8 1449 3766) (intervals 56 146348 12559) (buffers 984 139))




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#80121; Package emacs. (Sat, 03 Jan 2026 16:23:02 GMT) Full text and rfc822 format available.

Message #8 received at 80121 <at> debbugs.gnu.org (full text, mbox):

From: Richard Lawrence <rwl <at> recursewithless.net>
To: 80121 <at> debbugs.gnu.org
Subject: Re: bug#80121: 31.0.50; cond*/match* (or ...) patterns 
Date: Sat, 03 Jan 2026 17:22:20 +0100
[Message part 1 (text/plain, inline)]
rwl <at> recursewithless.net writes:

> The `progn' form which is setting all the bindings to nil is expanded
> from `(progn ,@clearing) a little ways below that comment.  It looks
> to me like this form is maybe missing a reference to `expression', or
> perhaps should be part of a larger form that contains `expression'.

Indeed, the attached patch appears to fix the issue.  But I'm not very
familiar with this code, so please verify that it's the right fix.

-- 
Best,
Richard

[0001-Fix-or-.-patterns-in-match.patch (text/x-diff, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#80121; Package emacs. (Sun, 04 Jan 2026 09:31:02 GMT) Full text and rfc822 format available.

Message #11 received at 80121 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Richard Lawrence <rwl <at> recursewithless.net>, Richard Stallman <rms <at> gnu.org>
Cc: 80121 <at> debbugs.gnu.org
Subject: Re: bug#80121: 31.0.50; cond*/match* (or ...) patterns
Date: Sun, 04 Jan 2026 11:30:18 +0200
> From: Richard Lawrence <rwl <at> recursewithless.net>
> Date: Sat, 03 Jan 2026 17:22:20 +0100
> 
> rwl <at> recursewithless.net writes:
> 
> > The `progn' form which is setting all the bindings to nil is expanded
> > from `(progn ,@clearing) a little ways below that comment.  It looks
> > to me like this form is maybe missing a reference to `expression', or
> > perhaps should be part of a larger form that contains `expression'.
> 
> Indeed, the attached patch appears to fix the issue.  But I'm not very
> familiar with this code, so please verify that it's the right fix.

Thanks, I've added Richard Stallman, who wrote that code, to this
discussion.  Richard, any comments to the patch?

> >From f593b96bca6acb7ff8fad8ef2cd9b69a84900cc5 Mon Sep 17 00:00:00 2001
> From: Richard Lawrence <rwl <at> recursewithless.net>
> Date: Sat, 3 Jan 2026 17:10:54 +0100
> Subject: [PATCH] Fix (or ...) patterns in match*
> 
> This is a draft fix for Bug#80121.
> 
> * lisp/emacs-lisp/cond-star.el (cond*-subpat): Add missing reference to
> 'expression' when clearing multiple backtrack aliases.
> ---
>  lisp/emacs-lisp/cond-star.el | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/lisp/emacs-lisp/cond-star.el b/lisp/emacs-lisp/cond-star.el
> index fc8e261339e..26cd858600c 100644
> --- a/lisp/emacs-lisp/cond-star.el
> +++ b/lisp/emacs-lisp/cond-star.el
> @@ -706,7 +706,7 @@ cond*-subpat
>                             (if (null (cdr clearing))
>                                 `(or ,expression
>                                      ,(car clearing))
> -                             `(progn ,@clearing))))))
> +                             `(or ,expression (progn ,@clearing)))))))
>                 (push expression expressions)))
>             ;; At end of (or...), EACH variable bound by any arm
>             ;; has a backtrack alias gensym.  At run time, that gensym's value
> -- 
> 2.39.5
> 




This bug report was last modified 7 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.