Subject: bug#63103: 30.0.50; nconc compiler optimization breaks user packages

From: Daniel Mendler <[email-masked]>
Date: Thu, 27 Apr 2023 08:37:36 +0200

On 4/27/23 07:44, Philip Kaludercic wrote:
>> The problem is that `(nconc list nil)` is optimized to `list`. However
>> improper lists like `(a b c . 0)` should be turned into `(a b c)`.
> 
> Where is this behaviour documented?

This behavior is not documented explicitly. However the docstring states
that "Only the last argument is not altered, and need not be a list".
Due to symmetry reasons it is not far-fetched to assume that when
`nconc' can be used to turn a proper list into an improper list, that
the inverse works too. Most of the docstrings do not specify functions
on such a detailed and formal level.

Maybe Stefan can give a bit more background regarding the support of
improper list for Elisp functions. The main use case I've observed is
for `completion-all-completions' which uses the last cdr to return the
base position of the completion. Iirc `cl-loop' also handles improper
lists.

Generally I'd be wary about changing the semantics of functions since
this leads to bugs which are hard to debug. One could decide to restrict
`nconc' to proper lists only, not only via the bytecompiler optimization
but also by erroring out if improper lists are passed as argument.

Probably it is easier to explicitly allow the last nil argument in the
bytecode optimizer specially to retain the existing behavior for
improper lists.

Daniel