Subject: bug#24641: 26.0.50; let-alist: Incorrect byte-compile warning about unused lexical variable

From: Philipp Stephani <[email-masked]>
Date: Sat, 08 Oct 2016 13:33:20 +0000

Philipp <[email-masked]> schrieb am Sa., 8. Okt. 2016 um 14:48 Uhr:

>
>
> $ cat /tmp/letalist.el
>
> ;; -*- lexical-binding: t; -*-
>
> (print
>
>  (let-alist '((outer . ((inner . value))))
>
>    (let-alist .outer .inner)))
>
>
>
> $ emacs -Q -batch -f batch-byte-compile /tmp/letalist.el
>
>
>
> In toplevel form:
>
> /tmp/letalist.el:2:1:Warning: Unused lexical variable ‘\.inner’
>
>
>
> This warning is incorrect because '.inner' is used in the inner
>
> let-alist form.
>
>
>
>
I've attached a patch.
From 1d731a6fd2d60a4645cbecd8502a04e4ed7932e3 Mon Sep 17 00:00:00 2001
From: Philipp Stephani <[email-masked]>
Date: Sat, 8 Oct 2016 15:29:32 +0200
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20consider=20nested=20let-alist?=
 =?UTF-8?q?=20forms?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

See Bug#24641.

* lisp/emacs-lisp/let-alist.el (let-alist--deep-dot-search): Don’t
consider symbols in nested ‘let-alist’ forms.

* test/lisp/emacs-lisp/let-alist-tests.el
(let-alist--deep-dot-search--nested): Add a unit test.
---
 lisp/emacs-lisp/let-alist.el            | 5 +++++
 test/lisp/emacs-lisp/let-alist-tests.el | 8 ++++++++
 2 files changed, 13 insertions(+)

diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el
index 3507a39..d706917 100644
--- a/lisp/emacs-lisp/let-alist.el
+++ b/lisp/emacs-lisp/let-alist.el
@@ -76,6 +76,11 @@ let-alist--deep-dot-search
         ;; with other results in the clause below.
         (list (cons data (intern (replace-match "" nil nil name)))))))
    ((not (consp data)) nil)
+   ((eq (car data) 'let-alist)
+    ;; For nested ‘let-alist’ forms, ignore symbols appearing in the
+    ;; inner body because they don’t refer to the alist currently
+    ;; being processed.  See Bug#24641.
+    (let-alist--deep-dot-search (cadr data)))
    (t (append (let-alist--deep-dot-search (car data))
               (let-alist--deep-dot-search (cdr data))))))
 
diff --git a/test/lisp/emacs-lisp/let-alist-tests.el b/test/lisp/emacs-lisp/let-alist-tests.el
index 80d418c..657a27a 100644
--- a/test/lisp/emacs-lisp/let-alist-tests.el
+++ b/test/lisp/emacs-lisp/let-alist-tests.el
@@ -88,4 +88,12 @@ let-alist--test-counter
                  '(cdr (assq 'baz (cdr (assq 'bar (cdr (assq 'foo var))))))))
   (should (equal (let-alist--access-sexp '..foo.bar.baz 'var) '.foo.bar.baz)))
 
+(ert-deftest let-alist--deep-dot-search--nested ()
+  "Check that nested `let-alist' forms don't generate spurious bindings.
+See Bug#24641."
+  (should (equal (let-alist--deep-dot-search '(foo .bar (baz .qux)))
+                 '((.bar . bar) (.qux . qux))))
+  (should (equal (let-alist--deep-dot-search '(foo .bar (let-alist .qux .baz)))
+                 '((.bar . bar) (.qux . qux)))))  ; no .baz
+
 ;;; let-alist.el ends here
-- 
2.10.0