diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2021-05-18 12:03:11 +0200 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2021-05-18 12:34:30 +0200 |
commit | be9db2b94d31a0afe3f93302558b3a78605244c7 (patch) | |
tree | ed6b70146ad94da66d8390ad9c1179f1255580da /lisp/emacs-lisp | |
parent | ed8c3303f945fbd2c16ece0e87d041c75ae05ff9 (diff) | |
download | emacs-be9db2b94d31a0afe3f93302558b3a78605244c7.tar.gz emacs-be9db2b94d31a0afe3f93302558b3a78605244c7.tar.bz2 emacs-be9db2b94d31a0afe3f93302558b3a78605244c7.zip |
Fix pcase 'rx' patterns with a single named submatch (bug#48477)
pcase 'rx' patterns with a single named submatch, like
(rx (let x "a"))
would always succeed because of an over-optimistic transformation.
Patterns with 0 or more than 1 named submatches were not affected.
Reported by Philipp Stephani.
* lisp/emacs-lisp/rx.el (rx--pcase-macroexpander):
Special case for a single named submatch.
* test/lisp/emacs-lisp/rx-tests.el (rx-pcase): Add tests.
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r-- | lisp/emacs-lisp/rx.el | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 1e3eb9c12b1..43bd84d9990 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1445,12 +1445,23 @@ following constructs: (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps)))) (nvars (length rx--pcase-vars))) `(and (pred stringp) - ,(if (zerop nvars) - ;; No variables bound: a single predicate suffices. - `(pred (string-match ,regexp)) + ,(pcase nvars + (0 + ;; No variables bound: a single predicate suffices. + `(pred (string-match ,regexp))) + (1 + ;; Create a match value that on a successful regexp match + ;; is the submatch value, 0 on failure. We can't use nil + ;; for failure because it is a valid submatch value. + `(app (lambda (s) + (if (string-match ,regexp s) + (match-string 1 s) + 0)) + (and ,(car rx--pcase-vars) (pred (not numberp))))) + (_ ;; Pack the submatches into a dotted list which is then ;; immediately destructured into individual variables again. - ;; This is of course slightly inefficient when NVARS > 1. + ;; This is of course slightly inefficient. ;; A dotted list is used to reduce the number of conses ;; to create and take apart. `(app (lambda (s) @@ -1463,7 +1474,7 @@ following constructs: (rx--reduce-right #'cons (mapcar (lambda (name) (list '\, name)) - (reverse rx--pcase-vars))))))))) + (reverse rx--pcase-vars)))))))))) ;; Obsolete internal symbol, used in old versions of the `flycheck' package. (define-obsolete-function-alias 'rx-submatch-n 'rx-to-string "27.1") |