Subject: bug#25678: 25.1; defcustom type `(file :must-match t)' seems not to work

From: Mauro Aranda <[email-masked]>
Date: Wed, 9 Sep 2020 14:21:11 -0300

Lars Ingebrigtsen <[email-masked]> writes:

> Mauro Aranda <[email-masked]> writes:
>
>> I think it makes sense to expand the impact of :must-match t to
>> Customization buffers, like in the attached patch.
>
> [...]
>
>> +  :match #'(lambda (widget value)
>> +             (or (not (widget-get widget :must-match))
>> +                 (file-exists-p value)))
>
> Makes sense to me.  I've now applied this to Emacs 28 (but I removed the
> #''s before the lambdas first (they're superfluous)).

I found that the :match function will return false positives when
:must-match is nil and value is not a string.  This can happen is
the defcustom is of type:
:type '(choice file (const nil))), and the value is nil, because we
check if nil matches with the widget file first.

Here's a patch to fix it.
From d6abe15da5ff39996ab4f5ebfbc3428e92017452 Mon Sep 17 00:00:00 2001
From: Mauro Aranda <[email-masked]>
Date: Wed, 9 Sep 2020 14:11:49 -0300
Subject: [PATCH] Fix :match function for the file widget

* lisp/wid-edit.el (file widget): Return nil if value is not a
  string.  (Bug#25678)
---
 lisp/wid-edit.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index e9799dc00f..bc2afc6a6f 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -3162,8 +3162,9 @@ 'file
                 #'completion-file-name-table
                 (not read-file-name-completion-ignore-case))
   :match (lambda (widget value)
-           (or (not (widget-get widget :must-match))
-               (file-exists-p value)))
+           (and (stringp value)
+                (or (not (widget-get widget :must-match))
+                    (file-exists-p value))))
   :validate (lambda (widget)
               (let ((value (widget-value widget)))
                 (unless (widget-apply widget :match value)
-- 
2.28.0