18

Byte compilation of my mode:

(defun dict-setup-expansions ()
  "Add `dict-mode' specific expansions."
  (set (make-local-variable 'er/try-expand-list) (list #'dict-mark-article)))

gives warning:

Warning: assignment to free variable `er/try-expand-list'

This is normal situation because er/try-expand-list is defined in external library expand-region.

My mode register extension to expand-region library but it is ok to run my mode without expand-region mode.

I think that proper way to deal with warning is to add declaration:

(defvar er/try-expand-list)

defvar docs say:

The `defvar' form also declares the variable as "special",
so that it is always dynamically bound even if `lexical-binding' is t.

I use -*- lexical-binding: t -*-. Does that mean that without defvar variable er/try-expand-list be in lexical scope and I have real bug?

gavenkoa
  • 3,352
  • 19
  • 36

1 Answers1

11

No, set and setq do not declare lexical variables. Only let does. Had you used let here you'd have a bug, but this is fine. The warning exists mostly to catch typos when using dynamic variables.

To make the warning go away use defvar as in your question, but do not quote the symbol.

  • Is wrapping into `eval-when-compile` redundant to just `defvar`? I see no warning without `eval-when-compile`. Seems that `eval-when-compile` is necessary if use active code, like `(require ...)`... – gavenkoa Mar 27 '16 at 14:35
  • 3
    Wrapping defvar would be redundant. –  Mar 27 '16 at 14:36