bug#48315: (ice-9 match) does not suport #nil

Taylan Kammer <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
This was mind-boggling to debug!

In syntax-rules, the pattern (x ...) will match #nil, since it
matches the empty list.  This can have surprising consequences.

Consider:

  (define-syntax test
    (syntax-rules ()
      ((test (x ...))
       (x ...))
      ((test x)
       x)))

  (test (+ 1 2))  ; => 3
  (test 123)      ; => 123
  (test #f)       ; => #f
  ;; However...
  (test #nil)     ; error


Anyway, attached is a patch to fix the issue in match.


- Taylan
0001-Fix-match-when-used-directly-on-the-nil-constant.patch (text/plain, 1.4 KB)
From b6d0b715a8bf0cc39b9fc3d46efeaf010f0d4351 Mon Sep 17 00:00:00 2001
From: Taylan Kammer <[email protected]>
Date: Wed, 12 May 2021 21:46:54 +0200
Subject: [PATCH] Fix match when used directly on the #nil constant.

* module/ice-9/match.upstream.scm (match): Make sure we don't match #nil
where we don't intend to.

Fixes <https://bugs.gnu.org/48315>.
---
 module/ice-9/match.upstream.scm | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/module/ice-9/match.upstream.scm b/module/ice-9/match.upstream.scm
index b1fc371b8..3b181b75b 100644
--- a/module/ice-9/match.upstream.scm
+++ b/module/ice-9/match.upstream.scm
@@ -269,9 +269,12 @@
      (match-syntax-error "missing match expression"))
     ((match atom)
      (match-syntax-error "no match clauses"))
-    ((match (app ...) (pat . body) ...)
-     (let ((v (app ...)))
-       (match-next v ((app ...) (set! (app ...))) (pat . body) ...)))
+    ;; The original implementation uses (app ...) not (op arg ...) here,
+    ;; but in Guile this would match #nil when it shouldn't.  Failing to
+    ;; match () doesn't matter since it leads to an error anyway.
+    ((match (op arg ...) (pat . body) ...)
+     (let ((v (op arg ...)))
+       (match-next v ((op arg ...) (set! (op arg ...))) (pat . body) ...)))
     ((match #(vec ...) (pat . body) ...)
      (let ((v #(vec ...)))
        (match-next v (v (set! v)) (pat . body) ...)))
-- 
2.30.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.