summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorMattias EngdegÄrd <mattiase@acm.org>2021-05-18 12:03:11 +0200
committerMattias EngdegÄrd <mattiase@acm.org>2021-05-18 12:34:30 +0200
commitbe9db2b94d31a0afe3f93302558b3a78605244c7 (patch)
treeed6b70146ad94da66d8390ad9c1179f1255580da /lisp/emacs-lisp
parented8c3303f945fbd2c16ece0e87d041c75ae05ff9 (diff)
downloademacs-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.el21
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")