Subject: bug#74718: 29.4; Huge metadata with flex completion style

From: Dmitry Gutov <[email-masked]>
Date: Tue, 10 Dec 2024 04:27:48 +0200

Hi Thierry,

On 07/12/2024 10:06, Thierry Volpiatto wrote:
> 
> The flex completion style uses a function
> (completion--flex-adjust-metadata) to create its display-sort-function.
> completion-all-completions calls completion--nth-completion which then
> uses setcdr on metadata to setup sort-function with this function.  At
> each call of completion-all-completions the metadata is growing quickly
> and become huge (see attached file).  In addition to the
> display-sort-function becoming huge, the objects are duplicated at each
> turn because there is no measure to prevent duplicates.

Thanks for the report.

> Here the offending code in minibuffer.el (in
> completion--nth-completion):
> 
> --8<---------------cut here---------------start------------->8---
>     (adjust-fn (get (cdr result-and-style) 'completion--adjust-metadata)))
>      (when (and adjust-fn metadata)
>        (setcdr metadata (cdr (funcall adjust-fn metadata))))
> --8<---------------cut here---------------end--------------->8---
> 
> the bug is reproductible easily with helm which allows examining the
> object while the session is running, here how to reproduce:
> 
> For example we will use `switch-to-buffer' (C-x b) with helm-mode enabled:
> 
> 1) Once helm is installed enable helm-mode:
> ...

Can you also reproduce it without Helm?

I've tried to do that with the default UI for a bit, and also with 
company-mode enabled (which also reuses this code). No luck triggering 
this so far.

To test this, I added a printing statement and re-evaluated the defun:

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 405ee21cdb2..6ae3c7b5ee3 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1310,6 +1310,7 @@ completion--nth-completion
           (adjust-fn (get (cdr result-and-style) 
'completion--adjust-metadata)))
      (when (and adjust-fn metadata)
        (setcdr metadata (cdr (funcall adjust-fn metadata))))
+    (message "%S" metadata)
      (if requote
          (funcall requote (car result-and-style) n)
        (car result-and-style))))