Subject: 25.1; Unused lexical variable when byte-compiling pcase with guards

From: Yuri Khan <[email-masked]>
Date: Sat, 1 Jul 2017 17:01:17 +0700

$ emacs -Q

C-x C-f test.el RET

;; -*- lexical-binding: t -*-

(defun foo (x)
  (pcase x
    ((and `(,bar ,baz)
          (guard (eq bar 'quux)))
     baz)))

C-x C-s
M-x byte-compile RET test.el RET

Observed output:

Compiling file /home/yuri/test.el at Sat Jul  1 16:27:36 2017
test.el:3:1:Warning: Unused lexical variable ‘bar’

Expected behavior: no warning, as the variable is used in the guard.

What is the byte compiler trying to tell me?

Upd. Hmm. I’ve read the output of (pp (macroexpand (pcase …))).

(if (consp x)
    (let* ((x (car x))
           (x (cdr x)))
      (if (consp x)
          (let* ((x (car x))
                 (x (cdr x)))
            (if (or (not (null x))
                    (not (let* ((bar x)) ;; ← one
                           (eq bar 'quux))))
                nil
              (let ((baz x)
                    (bar x)) ;; ← two
                baz)))
        nil))
  nil)

It binds ‘bar’ twice, once around the guard expression, and again
around the case body. It’s probably the second one that triggers the
warning.

In GNU Emacs 25.1.1 (x86_64-pc-linux-gnu, GTK+ Version 3.18.9)
 of 2016-12-13, modified by Debian built on lgw01-55
Windowing system distributor 'The X.Org Foundation', version 11.0.11804000
System Description:    Ubuntu 16.04.2 LTS

Configured using:
 'configure --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/lib
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --with-pop=yes
 --enable-locallisppath=/etc/emacs25:/etc/emacs:/usr/local/share/emacs/25.1/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/25.1/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/lib
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --with-pop=yes
 --enable-locallisppath=/etc/emacs25:/etc/emacs:/usr/local/share/emacs/25.1/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/25.1/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --with-x=yes --with-x-toolkit=gtk3
 --with-toolkit-scroll-bars 'CFLAGS=-g -O2 -fstack-protector-strong
 -Wformat -Werror=format-security -Wall' 'CPPFLAGS=-Wdate-time
 -D_FORTIFY_SOURCE=2' 'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro''

Configured features:
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GCONF GSETTINGS
NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB
TOOLKIT_SCROLL_BARS GTK3 X11

Important settings:
  value of $LC_MONETARY: en_RU.UTF-8
  value of $LC_NUMERIC: en_RU.UTF-8
  value of $LC_TIME: en_RU.UTF-8
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Emacs-Lisp

Minor modes in effect:
  diff-auto-refine-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent messages:
Wrote /home/yuri/test.el
Compiling /home/yuri/test.el...done
Wrote /home/yuri/test.elc
previous-line: Beginning of buffer [12 times]
Mark set [5 times]
<f2> C-g is undefined
Saving file /home/yuri/test.el...
Wrote /home/yuri/test.el
Compiling /home/yuri/test.el...done
Wrote /home/yuri/test.elc

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message format-spec rfc822 mml mml-sec
password-cache epg epg-config gnus-util mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils warnings help-fns
byte-opt compile comint ansi-color ring bytecomp byte-compile cl-extra
help-mode cl-loaddefs pcase cl-lib cconv dired two-column vc-git
diff-mode easymenu easy-mmode time-date mule-util tooltip eldoc electric
uniquify ediff-hook vc-hooks lisp-float-type mwheel x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list newcomment elisp-mode lisp-mode prog-mode register page
menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock
syntax facemenu font-core frame cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese charscript case-table epa-hook jka-cmpr-hook help
simple abbrev minibuffer cl-preloaded nadvice loaddefs button faces
cus-face macroexp files text-properties overlay sha1 md5 base64 format
env code-pages mule custom widget hashtable-print-readable backquote
dbusbind inotify dynamic-setting system-font-setting font-render-setting
move-toolbar gtk x-toolkit x multi-tty make-network-process emacs)

Memory information:
((conses 16 104547 9702)
 (symbols 48 21233 0)
 (miscs 40 85 207)
 (strings 32 19291 4424)
 (string-bytes 1 569482)
 (vectors 16 13692)
 (vector-slots 8 450722 6005)
 (floats 8 176 413)
 (intervals 56 841 680)
 (buffers 976 20)
 (heap 1024 41261 1188))