Subject: Re: bug#65411: 29.1; setopt of xref-after-jump-hook gives warning

From: Howard Melman <[email-masked]>
Date: Mon, 21 Aug 2023 09:19:23 -0400

> On Aug 21, 2023, at 8:01 AM, Eli Zaretskii <[email-masked]> wrote:
> 
>> From: Howard Melman <[email-masked]>
>> Date: Sun, 20 Aug 2023 20:21:39 -0400
>> Cc: [email-masked]
>> 
>>>> So why does it fail using setopt?
>>> 
>>> Because until xref is loaded, Emacs doesn't know that
>>> 'xref-pulse-momentarily' is a symbol of function, whereas the
>>> defcustom's type is 'hook', which stands for "a list of functions".
>> 
>> Well, that must be correct because doing this also worked fine:
>> 
>>  (declare-function xref-pulse-momentarily "xref" ())
>>  (setopt xref-after-jump-hook '(reposition-window xref-pulse-momentarily))
>> 

Thanks for the continued responses.

>> So I guess setopt defers the type check?
> 
> No, it just verifies that the symbol's function slot is valid.

I'd call that part of the type check, is it doing other stuff too?

>> I get the error when the hook is run (at which time xref is loaded
>> so I'm still confused about that).
> 
> declare-function doesn't provider an actual function definition, it
> just provides a declaration.  IOW, you lie to Emacs, and Emacs bites
> you when it can ;-)

Yes, I understand declare-function, but it feels extra mean that
Emacs decides it wants to bite for something and waits until after
I correct that to do so. ;)

>> I'm familiar with reading the lisp code but the innards of custom and
>> the c code are a bit beyond me.  Is it the custom-check-value property
>> in setopt--set?
> 
> Yes.
> 
>> If I'm supposed to resolve this warning on my own, then a comment
>> in setopt--set or something in setopt's docstring (or the manual)
>> mentioning the asynchrony would help.
> 
> setopt is a non-interactive version of defcustom.  Like defcustom will
> not accept a value that contradicts the :type of the option, so will
> setopt.  I don't think there's anything subtle to be documented here.

But something seems off.  Let me reiterate, I put this in my init:

    (setopt xref-after-jump-hook '(reposition-window xref-pulse-momentarily))

The value is properly formatted and is what custom would store in
custom-file had I used M-x custom.  In fact, if put this in the
custom-file's custom-set-variables' call:

    '(xref-after-jump-hook '(reposition-window xref-pulse-momentarily))

and restart emacs, it works fine, with no warning at init or run time.

So setopt behaves differently than defcustom, for the same value,
giving an unclear warning (with extra parentheses around the value
which I didn't put there and not mentioning anything being undefined)
at an odd time where the cause is already resolved at warning time.

I don't see how "Like defcustom will not accept a value that
contradicts the :type of the option, so will setopt." is the issue
here.

Howard