unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Dealing with obsoletion warnings in non-core code
@ 2020-09-28 14:35 Vasilij Schneidermann
  2020-09-28 17:32 ` Stefan Monnier
  2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
  0 siblings, 2 replies; 15+ messages in thread
From: Vasilij Schneidermann @ 2020-09-28 14:35 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1551 bytes --]

Here's something that keeps irking me when maintaining community
packages written back when Emacs 24.3 was a reasonable version to
support: With every new Emacs release I receive more and more
byte-compiler warnings that are tricky to silence.  One pattern that
keeps showing up is that of functions/variables the byte-compiler
doesn't know about (for example because these are only available in a
future Emacs release), for those it's possible to use a conditional
testing for the function/variable existence:

    (if (fboundp 'new-and-exciting-function)
        (new-and-exciting-function)
      (boring-function))

The same trick however cannot be used for functions/variables declared
obsoleted, the only construct I've found to work in this case is the
following:

    (with-suppressed-warnings ((obsolete old-but-useful-function))
      (if (fboundp 'recommended-function)
          (recommended-function)
        (old-but-useful-function)))

Ideally I'd like to be able to write the following instead to avoid the
needless repetition:

    (if (fboundp 'recommended-function)
        (recommended-function)
      (old-but-useful-function))

Is there something I'm overlooking here?  I've looked at core code and
it seems to mostly ignore this kind of compatibility issue and instead
drops all obsolete usage.  This is not always an option as community
package author.  Many authors and users just ignore warnings, especially
if they can't do anything about them.  This leads to fatigue and might
let them overlook actually important warnings.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 14:35 Dealing with obsoletion warnings in non-core code Vasilij Schneidermann
@ 2020-09-28 17:32 ` Stefan Monnier
  2020-09-28 18:16   ` Eli Zaretskii
  2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
  1 sibling, 1 reply; 15+ messages in thread
From: Stefan Monnier @ 2020-09-28 17:32 UTC (permalink / raw)
  To: emacs-devel

> The same trick however cannot be used for functions/variables declared
> obsoleted, the only construct I've found to work in this case is the
> following:
>
>     (with-suppressed-warnings ((obsolete old-but-useful-function))
>       (if (fboundp 'recommended-function)
>           (recommended-function)
>         (old-but-useful-function)))
>
> Ideally I'd like to be able to write the following instead to avoid the
> needless repetition:
>
>     (if (fboundp 'recommended-function)
>         (recommended-function)
>       (old-but-useful-function))

Indeed, it's a problem of which I'm aware but I don't know how to solve
it nicely.  Here's my thoughts about it so far:

I see how I could silence the obsolescence warning for:

      (if (fboundp 'old-but-useful-function)
          (old-but-useful-function)
        (recommended-function))

but that then gives you byte-compile warnings in older Emacsen because
of the use of a `recommended-function` they don't know about, and more
problematically it makes your code keep using the obsolete function even
when the all-dancing-all-singing `recommended-function` is
already available.

I guess we could try and add some kind of database of "replacements", so
when the byte-compiler sees (fboundp 'recommended-function) it knows to
silence warnings for `old-but-useful-function`, but that seems terribly
ad-hoc, will likely only work for some particular cases, and requires
the programmer to be aware of which `recommend-function` to test in
order to silence the warning.  Maybe it's still worth doing,
I don't know.


        Stefan




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 17:32 ` Stefan Monnier
@ 2020-09-28 18:16   ` Eli Zaretskii
  2020-09-28 18:34     ` Vasilij Schneidermann
  2020-09-28 19:24     ` Stefan Monnier
  0 siblings, 2 replies; 15+ messages in thread
From: Eli Zaretskii @ 2020-09-28 18:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Mon, 28 Sep 2020 13:32:47 -0400
> 
> > Ideally I'd like to be able to write the following instead to avoid the
> > needless repetition:
> >
> >     (if (fboundp 'recommended-function)
> >         (recommended-function)
> >       (old-but-useful-function))
> 
> Indeed, it's a problem of which I'm aware but I don't know how to solve
> it nicely.

What about something like the below?

  (if (> emacs-major-version NN)
    (defun recommended-function (...)
      ...))



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 18:16   ` Eli Zaretskii
@ 2020-09-28 18:34     ` Vasilij Schneidermann
  2020-09-28 19:00       ` Eli Zaretskii
  2020-09-28 19:24     ` Stefan Monnier
  1 sibling, 1 reply; 15+ messages in thread
From: Vasilij Schneidermann @ 2020-09-28 18:34 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 874 bytes --]

> What about something like the below?
> 
>   (if (> emacs-major-version NN)
>     (defun recommended-function (...)
>       ...))

You don't want a third-party package defining a potentially
non-conformant version of future built-in functionality (for example if
they take the definition from a specific Emacs version and it changes in
another one).  Users could mistake that for the real one.  Shimming may
be acceptable in a JavaScript world, but remember, they have invented
fixes to lack of namespacing and modules and we haven't, so their damage
from a package is global.

Besides, isn't the logic the wrong way around?  The recommended function
is something available in a newer Emacs version, so you'd test for an
older one and if the check is positive, define the shim.  Assuming you
can even, some functionality cannot be backported that easily.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 18:34     ` Vasilij Schneidermann
@ 2020-09-28 19:00       ` Eli Zaretskii
  0 siblings, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2020-09-28 19:00 UTC (permalink / raw)
  To: Vasilij Schneidermann; +Cc: monnier, emacs-devel

> Date: Mon, 28 Sep 2020 20:34:57 +0200
> From: Vasilij Schneidermann <mail@vasilij.de>
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> 
> >   (if (> emacs-major-version NN)
> >     (defun recommended-function (...)
> >       ...))
> 
> You don't want a third-party package defining a potentially
> non-conformant version of future built-in functionality

We've been using such shims in packages that supported both Emacs and
XEmacs, for eons.  I don't see how it's suddenly so wrong.

> (for example if they take the definition from a specific Emacs
> version and it changes in another one)

That's a separate problem, and will happen even if you only support
versions where the function is available.  It's why we try very hard
not to make backward-incompatible changes in public APIs.

> Besides, isn't the logic the wrong way around?  The recommended function
> is something available in a newer Emacs version, so you'd test for an
> older one and if the check is positive, define the shim.

You assume that the older one is removed?  That usually doesn't
happen.

> Assuming you can even, some functionality cannot be backported that
> easily.

If the functionality cannot be had at all, there's no problem: just
provide a no-op function by that name.

Anyway, you asked how to avoid warning messages, and I suggested a way
which should do that.  If that's not what you want, fine; I tried to
help you.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 18:16   ` Eli Zaretskii
  2020-09-28 18:34     ` Vasilij Schneidermann
@ 2020-09-28 19:24     ` Stefan Monnier
  2020-09-29 14:07       ` Eli Zaretskii
  1 sibling, 1 reply; 15+ messages in thread
From: Stefan Monnier @ 2020-09-28 19:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> > Ideally I'd like to be able to write the following instead to avoid the
>> > needless repetition:
>> >
>> >     (if (fboundp 'recommended-function)
>> >         (recommended-function)
>> >       (old-but-useful-function))
>> 
>> Indeed, it's a problem of which I'm aware but I don't know how to solve
>> it nicely.
>
> What about something like the below?
>
>   (if (> emacs-major-version NN)
>     (defun recommended-function (...)
>       ...))

I'm not sure I understand what you mean.  You're suggesting to replace
the `fboundp` test above with something like:

    (if (< emacs-major-version NN)
      (defun recommended-function (...)
        ...
        (old-but-useful-function)
        ...))

    [...]

        (recommended-function)

?  If so, I fail to see how it helps.  It will still result in an obsolete
warning on new Emacsen (and adds an "unknown function" warning on old ones).

Or did I misunderstand your suggestion?


        Stefan




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 14:35 Dealing with obsoletion warnings in non-core code Vasilij Schneidermann
  2020-09-28 17:32 ` Stefan Monnier
@ 2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
  2020-09-29  8:28   ` Gregory Heytings via Emacs development discussions.
  2020-09-29 13:11   ` Stefan Monnier
  1 sibling, 2 replies; 15+ messages in thread
From: Gregory Heytings via Emacs development discussions. @ 2020-09-29  8:21 UTC (permalink / raw)
  To: Vasilij Schneidermann; +Cc: emacs-devel


> The same trick however cannot be used for functions/variables declared 
> obsoleted, the only construct I've found to work in this case is the 
> following:
>
>    (with-suppressed-warnings ((obsolete old-but-useful-function))
>      (if (fboundp 'recommended-function)
>          (recommended-function)
>        (old-but-useful-function)))
>
> Ideally I'd like to be able to write the following instead to avoid the 
> needless repetition:
>
>    (if (fboundp 'recommended-function)
>        (recommended-function)
>      (old-but-useful-function))

Here's a proposed solution:

(defmacro call (fun &rest args) `(funcall (intern (symbol-name ,fun)) ,@args))

(defun select-text (text)
   (if (> emacs-major-version 25)
       (call 'gui-select-text text)
     (call 'x-select-text text)))

It avoids the needless repetition, and does not give warnings on older 
Emacsen that do not know about gui-select-text, or on newer Emacsen that 
have x-select-text marked as obsolete.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
@ 2020-09-29  8:28   ` Gregory Heytings via Emacs development discussions.
  2020-09-29  9:33     ` Gregory Heytings via Emacs development discussions.
  2020-09-29 13:11   ` Stefan Monnier
  1 sibling, 1 reply; 15+ messages in thread
From: Gregory Heytings via Emacs development discussions. @ 2020-09-29  8:28 UTC (permalink / raw)
  To: Vasilij Schneidermann; +Cc: emacs-devel


>> The same trick however cannot be used for functions/variables declared 
>> obsoleted, the only construct I've found to work in this case is the 
>> following:
>>
>>    (with-suppressed-warnings ((obsolete old-but-useful-function))
>>      (if (fboundp 'recommended-function)
>>          (recommended-function)
>>        (old-but-useful-function)))
>> 
>> Ideally I'd like to be able to write the following instead to avoid the 
>> needless repetition:
>>
>>    (if (fboundp 'recommended-function)
>>        (recommended-function)
>>      (old-but-useful-function))
>
> Here's a proposed solution:
>
> (defmacro call (fun &rest args) `(funcall (intern (symbol-name ,fun)) ,@args))
>
> (defun select-text (text)
>  (if (> emacs-major-version 25)
>      (call 'gui-select-text text)
>    (call 'x-select-text text)))
>
> It avoids the needless repetition, and does not give warnings on older 
> Emacsen that do not know about gui-select-text, or on newer Emacsen that 
> have x-select-text marked as obsolete.
>

P.S.:

Obviously

(defun select-text (text)
   (if (fboundp 'gui-select-text)
       (call 'gui-select-text text)
     (call 'x-select-text text)))

also works.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29  8:28   ` Gregory Heytings via Emacs development discussions.
@ 2020-09-29  9:33     ` Gregory Heytings via Emacs development discussions.
  0 siblings, 0 replies; 15+ messages in thread
From: Gregory Heytings via Emacs development discussions. @ 2020-09-29  9:33 UTC (permalink / raw)
  To: Vasilij Schneidermann; +Cc: emacs-devel


>>> The same trick however cannot be used for functions/variables declared 
>>> obsoleted, the only construct I've found to work in this case is the 
>>> following:
>>>
>>>    (with-suppressed-warnings ((obsolete old-but-useful-function))
>>>      (if (fboundp 'recommended-function)
>>>          (recommended-function)
>>>        (old-but-useful-function)))
>>> 
>>> Ideally I'd like to be able to write the following instead to avoid 
>>> the needless repetition:
>>>
>>>    (if (fboundp 'recommended-function)
>>>        (recommended-function)
>>>      (old-but-useful-function))
>> 
>> Here's a proposed solution:
>> 
>> (defmacro call (fun &rest args) `(funcall (intern (symbol-name ,fun)) ,@args))
>> 
>> (defun select-text (text)
>>  (if (> emacs-major-version 25)
>>      (call 'gui-select-text text)
>>    (call 'x-select-text text)))
>> 
>> It avoids the needless repetition, and does not give warnings on older 
>> Emacsen that do not know about gui-select-text, or on newer Emacsen 
>> that have x-select-text marked as obsolete.
>> 
>
> P.S.:
>
> Obviously
>
> (defun select-text (text)
>  (if (fboundp 'gui-select-text)
>      (call 'gui-select-text text)
>    (call 'x-select-text text)))
>
> also works.
>

P.P.S.:

And for variables, the equivalent would of course be:

(defmacro assign (var val) `(set (intern (symbol-name ,var)) ,val))

(if (boundp 'switch-to-prev-buffer-skip)
     (assign 'switch-to-prev-buffer-skip t)
   (assign 'switch-to-visible-buffer t))



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
  2020-09-29  8:28   ` Gregory Heytings via Emacs development discussions.
@ 2020-09-29 13:11   ` Stefan Monnier
  2020-09-29 14:11     ` Gregory Heytings via Emacs development discussions.
  2020-09-29 14:55     ` T.V Raman
  1 sibling, 2 replies; 15+ messages in thread
From: Stefan Monnier @ 2020-09-29 13:11 UTC (permalink / raw)
  To: Gregory Heytings via Emacs development discussions.
  Cc: Gregory Heytings, Vasilij Schneidermann

> Here's a proposed solution:
>
> (defmacro call (fun &rest args) `(funcall (intern (symbol-name ,fun)) ,@args))
>
> (defun select-text (text)
>   (if (> emacs-major-version 25)
>       (call 'gui-select-text text)
>     (call 'x-select-text text)))

That's just obfuscating the code (which will prevent the compiler from
detecting some real errors such as when you have a typo in the
function's name or when you don't provide the right number of args), and
might be defeated by compiler optimizations.

I think the OP's question was how to "do it right", rather than how to
work around the problem.


        Stefan




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-28 19:24     ` Stefan Monnier
@ 2020-09-29 14:07       ` Eli Zaretskii
  0 siblings, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2020-09-29 14:07 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Mon, 28 Sep 2020 15:24:36 -0400
> 
> > What about something like the below?
> >
> >   (if (> emacs-major-version NN)
> >     (defun recommended-function (...)
> >       ...))
> 
> I'm not sure I understand what you mean.  You're suggesting to replace
> the `fboundp` test above with something like:
> 
>     (if (< emacs-major-version NN)
>       (defun recommended-function (...)
>         ...
>         (old-but-useful-function)
>         ...))

No, I didn't suggest to call old-but-useful-function.  I suggested to
implement recommended-function or its close emulation.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29 13:11   ` Stefan Monnier
@ 2020-09-29 14:11     ` Gregory Heytings via Emacs development discussions.
  2020-09-29 14:46       ` Stefan Monnier
  2020-09-29 14:55     ` T.V Raman
  1 sibling, 1 reply; 15+ messages in thread
From: Gregory Heytings via Emacs development discussions. @ 2020-09-29 14:11 UTC (permalink / raw)
  To: emacs-devel; +Cc: Stefan Monnier, Vasilij Schneidermann


Hi Stefan,

I gave the two macros a better name, they are now:

(defmacro funcall-no-warn (fun &rest args) `(funcall (intern (symbol-name ,fun)) ,@args))
(defmacro set-no-warn (var val) `(set (intern (symbol-name ,var)) ,val))

and should be used as follows:

(if (fboundp 'new-function)
     (funcall-no-warn 'new-function arg ...)
   (funcall-no-warn 'old-function arg ...))

(if (boundp 'new-variable)
     (set-no-warn 'new-variable value)
   (set-no-warn 'old-variable value))

>
> That's just obfuscating the code
>

You probably meant: Indeed, that Just Works^TM, congratulations! ;-)

>
> (which will prevent the compiler from detecting some real errors such as 
> when you have a typo in the function's name or when you don't provide 
> the right number of args)
>

Indeed.  If there's another way to do this while detecting errors at 
compilation time, that would be even better.  OTOH, this will quickly 
raise a runtime error in case of typos or wrong number of arguments, which 
is unlikely to get unnoticed by the maintainer.  Of course I'm not 
advocating to use this everywhere.

>
> and might be defeated by compiler optimizations.
>

It might be, but AFAICS it is not.  I forgot to mention that I tested the 
above macros on Emacs 21, 22, 23, 24, 25, 26, 27 and 28.  As I said, it 
Just Works^TM.

>
> I think the OP's question was how to "do it right", rather than how to 
> work around the problem.
>

I don't know.  It's just my proposed solution.  OTOH, I don't see how he 
could "do it right" when his problem statement mentions that he wants to 
support old Emacs versions, which by definition nobody can improve 
anymore.

Your idea of of a database of replacements might work, but it has to be 
implemented, and for the use case the OP has in mind it will not be useful 
before Emacs 3X.

Gregory



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29 14:11     ` Gregory Heytings via Emacs development discussions.
@ 2020-09-29 14:46       ` Stefan Monnier
  2020-09-29 15:36         ` Gregory Heytings via Emacs development discussions.
  0 siblings, 1 reply; 15+ messages in thread
From: Stefan Monnier @ 2020-09-29 14:46 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Vasilij Schneidermann, emacs-devel

> Your idea of of a database of replacements might work, but it has to be
> implemented, and for the use case the OP has in mind it will not be useful
> before Emacs 3X.

Emacs-3X is what I'm interested in.  If I only cared about "current
Emacs", then I wouldn't be working on Emacs itself ;-)


        Stefan




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29 13:11   ` Stefan Monnier
  2020-09-29 14:11     ` Gregory Heytings via Emacs development discussions.
@ 2020-09-29 14:55     ` T.V Raman
  1 sibling, 0 replies; 15+ messages in thread
From: T.V Raman @ 2020-09-29 14:55 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: Gregory Heytings via Emacs development discussions.,
	Gregory Heytings, Vasilij Schneidermann

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=gb18030, Size: 299 bytes --]

in the meantime, I've been using file-local variables  by setting
byte-compiler-warning to (not obsolete) works for small file units where
the file-level warning shut off doesn't hide other real obsolete
warnings that deserve fixing 
-- 

Thanks,

--Raman
7©4 Id: kg:/m/0285kf1  •0Ü8



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Dealing with obsoletion warnings in non-core code
  2020-09-29 14:46       ` Stefan Monnier
@ 2020-09-29 15:36         ` Gregory Heytings via Emacs development discussions.
  0 siblings, 0 replies; 15+ messages in thread
From: Gregory Heytings via Emacs development discussions. @ 2020-09-29 15:36 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Vasilij Schneidermann, emacs-devel


>> Your idea of of a database of replacements might work, but it has to be 
>> implemented, and for the use case the OP has in mind it will not be 
>> useful before Emacs 3X.
>
> Emacs-3X is what I'm interested in.  If I only cared about "current 
> Emacs", then I wouldn't be working on Emacs itself ;-)
>

Being interested in Emacs 3X does not conflict with being interested in 
Emacs 2X _users_ ;-)



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-09-29 15:36 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-28 14:35 Dealing with obsoletion warnings in non-core code Vasilij Schneidermann
2020-09-28 17:32 ` Stefan Monnier
2020-09-28 18:16   ` Eli Zaretskii
2020-09-28 18:34     ` Vasilij Schneidermann
2020-09-28 19:00       ` Eli Zaretskii
2020-09-28 19:24     ` Stefan Monnier
2020-09-29 14:07       ` Eli Zaretskii
2020-09-29  8:21 ` Gregory Heytings via Emacs development discussions.
2020-09-29  8:28   ` Gregory Heytings via Emacs development discussions.
2020-09-29  9:33     ` Gregory Heytings via Emacs development discussions.
2020-09-29 13:11   ` Stefan Monnier
2020-09-29 14:11     ` Gregory Heytings via Emacs development discussions.
2020-09-29 14:46       ` Stefan Monnier
2020-09-29 15:36         ` Gregory Heytings via Emacs development discussions.
2020-09-29 14:55     ` T.V Raman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).