Subject: bug#78810: 30.1; `pp' expectation of `emacs-lisp-mode-syntax-table' etc.

From: Stefan Monnier <[email-masked]>
Date: Tue, 17 Jun 2025 11:52:29 -0400

>> `pp' was redefined in Emacs 30.1, introducing quite a few changes in
>> behavior, including the _default_ behavior.  As the function is a basic
>> workhorse, these behavior changes can be widespread.
>> 
>> The new definition:
>> 
>> (defun pp (object &optional stream)
>>   "..."
>>   (cond
>>    ((and (eq (or stream standard-output) (current-buffer))
>>          ;; Make sure the current buffer is setup sanely.
>>          (eq (syntax-table) emacs-lisp-mode-syntax-table)
>>          (eq indent-line-function #'lisp-indent-line))
>>     ;; Skip the buffer->string->buffer middle man.
>>     (funcall pp-default-function object)
>>     ;; Preserve old behavior of (usually) finishing with a newline.
>>     (unless (bolp) (insert "\n")))
>>    (t
>>     (princ (pp-to-string object) (or stream standard-output)))))
>> 
>> The old definition wass just that `cond' else clause:
>> 
>>   (princ (pp-to-string object) (or stream standard-output))
>> 
>> Is the first `cond' clause "sanity" check really a good one for use by
>> `pp-default-function' - sufficient and necessary?  I wonder...
>> 
>> For one thing, the option value can be _any_ function.  The _doc_ says
>> the function should accept 0 or 1 arg and that it "can presume that the
>> buffer is setup for Lisp syntax."  But the defcustom code doesn't
>> support/ensure either of those things.
>> 
>> For another thing, that check for a "sane" buffer setup precludes using
>> `pp-default-function' with a buffer whose syntax table isn't exactly
>> `emacs-lisp-mode-syntax-table', which means it can't be used for buffers
>> in `lisp-data-mode'.  Is that really TRT?  Is there some reason not to
>> use `pp-default-function' with that mode's syntax table?
>> 
>> And why the `indent-line-function' requirement?  Does `pp's use of
>> `pp-default-function' really need its value to be `lisp-indent-line'?
>> That seems fragile - or else unncessary.
>> 
>> If these constraints are necessary for option `pp-default-function',
>> then its doc had really better proclaim them as such, no?  The doc (if
>> not the defcustom code itself) had better tell users that the function
>> can only be used in a buffer with that syntax table and with that value
>> of `indent-line-function'.
>> 
>> I can imagine existing pre-30.1 code ending up (after some debugging)
>> changing some `pp' calls to (insert (pp-to-string...)), to fix problems
>> created by this `pp' redefinition.  Or as `bookmark.el' did, to bind
>> `pp-default-function' to `pp-28' around `pp' calls.
>> 
>> And why is the option called `pp-default-function'?  It's a user option,
>> and it's used unconditionally - not to provide some function by
>> _default_.  It should be called `pp-printer-function' or `pp-function'
>> or some such.  (The FIXME comment refers to it as a "pretty printer"
>> function.)
>> 
>> My sense is that the 30.1 changes to `pp' were misguided (especially
>> changing the _default_ behavior).  Call me bad for saying that's what I
>> smell.  I hope I'm very wrong.
>
> Stefan, any comments?

Not, really, no, expect that I don't see any actual bug reported in that
long explanation and that Drew seems to miss the fact that the first
branch of the `cond` is basically an optimization.

        Stefan