Subject: bug#64101: 29.0.91; Eglot inlay hints rendered out of order

From: Milan Jovanovic <[email-masked]>
Date: Mon, 19 Jun 2023 23:05:49 +0200

Looks like overlays render order depends on before-string/after-string property (beside priority).
Type hints overlays are ‘before-string and function parameter hints overlays are ‘after-string (so parameter hint parts are sorted by overlay descending priority).
If you change it to ‘before-string also (and adjust overlay start/end to be as in type hints) it will work as it should.

Btw. I still don’t understand why parts of one hint can’t be simply merged.

Anyway, my recipe to recreate issue:

% rust-analyzer --version
rust-analyzer 1.70.0 (90c54180 2023-05-31)  —> last rustup version (`rustup component add rust-analyzer`)

% /Applications/Emacs.app/Contents/MacOS/Emacs --version                           
GNU Emacs 29.0.91

% ls .emacs.d
auto-save-list elpa
ls .emacs.d/elpa 
archives            eglot-1.15          eglot-1.15.signed   eldoc-1.14.0        eldoc-1.14.0.signed gnupg

(eglot.el is patched with diff from João email)

% cargo new inlay-hints

>>> paste  this code into inlay-hints/src/main.rs

fn main() {
  let mut c = vec![1,2,3];
  c.insert(0, 0);
}

<<<<

% cd inlay-hints

% /Applications/Emacs.app/Contents/MacOS/Emacs src/main.rs -f rust-ts-mode -f eglot

Eglot events:

(:jsonrpc "2.0" :id 13 :result
	  [(:position
	    (:line 1 :character 11)
	    :label
	    [(:value ": ")
	     (:value "Vec" :location
		     (:uri "file:///Users/milan/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs" :range
			   (:start
			    (:line 395 :character 11)
			    :end
			    (:line 395 :character 14))))
	     (:value "<i32>")]
	    :kind 1 :paddingLeft :json-false :paddingRight :json-false)
	   (:position
	    (:line 2 :character 11)
	    :label
	    [(:value "index" :location
		     (:uri "file:///Users/milan/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs" :range
			   (:start
			    (:line 1434 :character 29)
			    :end
			    (:line 1434 :character 34))))
	     (:value ":")]
	    :kind 2 :paddingLeft :json-false :paddingRight t)
	   (:position
	    (:line 2 :character 13)
	    :label
	    [(:value "element" :location
		     (:uri "file:///Users/milan/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs" :range
			   (:start
			    (:line 1434 :character 43)
			    :end
			    (:line 1434 :character 50))))
	     (:value ":")]
	    :kind 2 :paddingLeft :json-false :paddingRight t)])

Trace output:
======================================================================
1 -> (make-overlay 25 26 nil t)
1 <- make-overlay: #<overlay from 25 to 26 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> before-string #(": " 0 1 (face eglot-type-hint-face cursor 1) 1 2 (face eglot-type-hint-face)))
1 <- overlay-put: #(": " 0 1 (face eglot-type-hint-face cursor 1) 1 2 (face eglot-type-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> priority 0)
1 <- overlay-put: 0
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 25 26 nil t)
1 <- make-overlay: #<overlay from 25 to 26 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> before-string #("Vec" 0 3 (face eglot-type-hint-face)))
1 <- overlay-put: #("Vec" 0 3 (face eglot-type-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> priority 1)
1 <- overlay-put: 1
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 25 26 nil t)
1 <- make-overlay: #<overlay from 25 to 26 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> before-string #("<i32>" 0 5 (face eglot-type-hint-face)))
1 <- overlay-put: #("<i32>" 0 5 (face eglot-type-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> priority 2)
1 <- overlay-put: 2
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 25 to 26 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 51 52 nil nil nil)
1 <- make-overlay: #<overlay from 51 to 52 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> after-string #("index" 0 5 (face eglot-parameter-hint-face)))
1 <- overlay-put: #("index" 0 5 (face eglot-parameter-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> priority 0)
1 <- overlay-put: 0
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 51 52 nil nil nil)
1 <- make-overlay: #<overlay from 51 to 52 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> after-string #(": " 0 2 (face eglot-parameter-hint-face)))
1 <- overlay-put: #(": " 0 2 (face eglot-parameter-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> priority 1)
1 <- overlay-put: 1
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 51 to 52 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 53 54 nil nil nil)
1 <- make-overlay: #<overlay from 53 to 54 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> after-string #("element" 0 7 (face eglot-parameter-hint-face)))
1 <- overlay-put: #("element" 0 7 (face eglot-parameter-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> priority 0)
1 <- overlay-put: 0
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (make-overlay 53 54 nil nil nil)
1 <- make-overlay: #<overlay from 53 to 54 in main.rs>
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> after-string #(": " 0 2 (face eglot-parameter-hint-face)))
1 <- overlay-put: #(": " 0 2 (face eglot-parameter-hint-face))
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> priority 1)
1 <- overlay-put: 1
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--inlay-hint t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> evaporate t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--overlay t)
1 <- overlay-put: t
======================================================================
1 -> (overlay-put #<overlay from 176 to 177 in *ielm*> priority 1000)
1 <- overlay-put: 1000
======================================================================
1 -> (overlay-put #<overlay from 176 to 177 in *ielm*> face show-paren-match)
1 <- overlay-put: show-paren-match
======================================================================
1 -> (overlay-put #<overlay from 164 to 165 in *ielm*> priority 1000)
1 <- overlay-put: 1000
======================================================================
1 -> (overlay-put #<overlay from 164 to 165 in *ielm*> face show-paren-match)
1 <- overlay-put: show-paren-match

> On 19. 6. 2023., at 21:08, João Távora <[email-masked]> wrote:
> 
> On Mon, Jun 19, 2023 at 7:06 PM Milan Jovanovic <[email-masked]> wrote:
> 
>> So, you fix did solve original Krzysztof report (and my original report) for more complex type hints but now I have the same issue with argument hints.
> 
> Yes, and I've already replied to you that I can't reproduce
> your error.  So maybe you should follow the instructions
> of
> 
>  https://joaotavora.github.io/eglot/#Troubleshooting-Eglot
> 
> so that you can provide a bullet-proof reproduction recipe.
> 
> So far, you haven't done that.  You just send me snippets of
> Rust code and I assume I should paste them into my own
> Emacs.  And there, I can't reproduce the problem.
> 
> IOW, I don't doubt that there's a problem in Eglot, but I
> need you to patiently craft a mail with the full recipe, i.e.
> the fullest -- and simplest -- account possible of your
> problem.
> 
>> Example:
>> 
>> fn main () {
>>   let mut c = vec![1,2,3];
>>   c.insert(0, 0);
>> }
>> 
> 
> Here, again, I see the correct inlay hints.
> 
> Here's my recipe.
> 
> $ cd /tmp
> $ cargo new bla
> $ cd bla
> $ rust-analyzer --version
> rust-analyzer 1 (cd3bf9fe51 2023-06-18)
> $ emacs --version
> ~/Source/Emacs/emacs/src/emacs --version
> GNU Emacs 30.0.50
> Development version 075e77ac4493 on master branch; build date 2023-06-19.
> ...
> <actually I have eglot.el patched with the latest patch>
> $ emacs -Q -f package-initialize src/main.rs -f eglot
> 
> Now I wait a little bit for the connection to stabilize and then type in your
> main.rs content.  If the inlay hints don't immediately appear, just add and
> delete a character anywhere in the buffer.  When they do appear, they appear
> correctly.
> 
> My rust-mode.el is version 1.0.5, but I've tried successfully with rust-ts-mode
> as well.
> 
> And by the way, this is the trace of the make-overlay and overlay-put
> functions
> 
> ======================================================================
> 1 -> (make-overlay 53 54 nil nil nil)
> 1 <- make-overlay: #<overlay from 53 to 54 in main.rs>
> ======================================================================
> 1 -> (overlay-put #<overlay from 53 to 54 in main.rs> after-string
> #("index: " 0 7 (face eglot-parameter-hint-face)))
> 1 <- overlay-put: #("index: " 0 7 (face eglot-parameter-hint-face))
> ======================================================================
> 1 -> (overlay-put #<overlay from 53 to 54 in main.rs> priority 0)
> 1 <- overlay-put: 0
> ======================================================================
> 1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--inlay-hint t)
> 1 <- overlay-put: t
> ======================================================================
> 1 -> (overlay-put #<overlay from 53 to 54 in main.rs> evaporate t)
> 1 <- overlay-put: t
> ======================================================================
> 1 -> (overlay-put #<overlay from 53 to 54 in main.rs> eglot--overlay t)
> 1 <- overlay-put: t
> ======================================================================
> 1 -> (make-overlay 56 57 nil nil nil)
> 1 <- make-overlay: #<overlay from 56 to 57 in main.rs>
> ======================================================================
> 1 -> (overlay-put #<overlay from 56 to 57 in main.rs> after-string
> #("element: " 0 9 (face eglot-parameter-hint-face)))
> 1 <- overlay-put: #("element: " 0 9 (face eglot-parameter-hint-face))
> ======================================================================
> 1 -> (overlay-put #<overlay from 56 to 57 in main.rs> priority 0)
> 1 <- overlay-put: 0
> ======================================================================
> 1 -> (overlay-put #<overlay from 56 to 57 in main.rs> eglot--inlay-hint t)
> 1 <- overlay-put: t
> ======================================================================
> 1 -> (overlay-put #<overlay from 56 to 57 in main.rs> evaporate t)
> 1 <- overlay-put: t
> ======================================================================
> 1 -> (overlay-put #<overlay from 56 to 57 in main.rs> eglot--overlay t)
> 1 <- overlay-put: t
> 
> So, as you can see, the server isn't supplying different hints for
> "index" and ":".  So I can't reproduce your error, you must be
> using a different version of rust analyzer or something like that.
> 
> This is the relevant portion of my Eglot events buffer:
> 
> (:jsonrpc "2.0" :id 39 :result
>          [(:position (:line 1 :character 12) :label
>                      [(:value ": ")
>                       (:value "Vec" :location
>                               (:uri
> 
> "file:///usr/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs"
>                                :range
>                                (:start (:line 395 :character 11) :end
>                                        (:line 395 :character 14))))
>                       (:value "<i32>")]
>                      :kind 1 :textEdits
>                      [(:range
>                        (:start (:line 1 :character 12) :end
>                                (:line 1 :character 12))
>                        :newText ": Vec<i32>")]
>                      :paddingLeft :json-false :paddingRight
>                      :json-false)
>           (:position (:line 2 :character 12) :label
>                      [(:value "index:" :location
>                               (:uri
> 
> "file:///usr/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs"
>                                :range
>                                (:start (:line 1434 :character 29)
>                                        :end
>                                        (:line 1434 :character 34))))]
>                      :kind 2 :paddingLeft :json-false :paddingRight t)
>           (:position (:line 2 :character 15) :label
>                      [(:value "element:" :location
>                               (:uri
> 
> "file:///usr/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs"
>                                :range
>                                (:start (:line 1434 :character 43)
>                                        :end
>                                        (:line 1434 :character 50))))]
>                      :kind 2 :paddingLeft :json-false :paddingRight t)])
> 
> João