diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2021-02-28 13:06:24 +0100 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2021-02-28 13:06:24 +0100 |
commit | bdea1883cc8feb8a607c3d05191e7dc8d12f0aa0 (patch) | |
tree | 93d93a3c7f2fc7b0aa821a128be8c306645a7519 /test/lisp/emacs-lisp/rx-tests.el | |
parent | aad8ffafa89fe46ff5d63bd0127274f74019d50f (diff) | |
download | emacs-bdea1883cc8feb8a607c3d05191e7dc8d12f0aa0.tar.gz |
Fix pcase 'rx' pattern match-data bug
The pcase 'rx' pattern would in some cases allow the match data to be
clobbered before it is read. For example:
(pcase "PQR"
((and (rx (let a nonl)) (rx ?z)) (list 'one a))
((rx (let b ?Q)) (list 'two b)))
The above returned (two "P") instead of the correct (two "Q").
This occurred because the calls to string-match and match-string were
presented as separate patterns to pcase, which would interleave them
with other patterns.
As a remedy, combine string matching and match-data extraction into a
single pcase pattern. This introduces a slight inefficiency for two
or more submatches as they are grouped into a list structure which
then has to be destructured.
Found by Stefan Monnier. See discussion at
https://lists.gnu.org/archive/html/emacs-devel/2021-02/msg02010.html
* lisp/emacs-lisp/rx.el (rx--reduce-right): New helper.
(rx [pcase macro]): Combine string-match and match-string calls into a
single pcase pattern.
* test/lisp/emacs-lisp/rx-tests.el (rx-pcase): Add test cases.
Diffstat (limited to 'test/lisp/emacs-lisp/rx-tests.el')
-rw-r--r-- | test/lisp/emacs-lisp/rx-tests.el | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el index fecdcf55aff..2dd1bca22d1 100644 --- a/test/lisp/emacs-lisp/rx-tests.el +++ b/test/lisp/emacs-lisp/rx-tests.el @@ -156,6 +156,8 @@ "....."))) (ert-deftest rx-pcase () + (should (equal (pcase "i18n" ((rx (let x (+ digit))) (list 'ok x))) + '(ok "18"))) (should (equal (pcase "a 1 2 3 1 1 b" ((rx (let u (+ digit)) space (let v (+ digit)) space @@ -176,6 +178,12 @@ ((rx nonl) 'wrong) (_ 'correct)) 'correct)) + (should (equal (pcase "PQR" + ((and (rx (let a nonl)) (rx ?z)) + (list 'one a)) + ((rx (let b ?Q)) + (list 'two b))) + '(two "Q"))) (should (equal (pcase-let (((rx ?B (let z nonl)) "ABC")) (list 'ok z)) '(ok "C"))) |