Subject: Re: 30.0.50; [BUG] Rust eglot tuple struct field completion

From: João Távora <[email-masked]>
Date: Wed, 22 Mar 2023 10:37:49 +0000

Ruijie Yu <[email-masked]> writes:

> CC'ing João because eglot.  Thanks.
>
>> I can't word it, so let me explain via an example.  The Emacs in
>> question was built a few days ago, FTR.
>>
>> Also, note that I am using rust-ts-mode as the major mode, since
>> it is the only builtin rust major mode, with the corresponding grammar
>> lib cloned and built moments ago.
>>
>> $ cd "$(mktemp -d)"
>> $ cargo init --name foo --lib
>> $ emacs -Q src/lib.rs
>>
>> Replace src/lib.rs with the following content, then revert buffer and
>> run `eglot':
>>
>> //  -*- mode: rust-ts; -*-
>> /// 0..=10
>> #[derive(Default)]
>> struct Foo(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32);
>>
>> fn foo(f: Foo) -> u32 {
>>     f.
>> }
>>
>>
>> Put point after "f.", and type any number between (inclusive) 0 and 10,
>> and type TAB.  

Hi, I could reproduce this, if instead of TAB I type M-TAB (or the
equivalent C-M-i, both run completion-at-point).  Rust-rs-mode is not
needed (rust-mode from ELPA is the same).

I'm not sure yet this isn't a server bug.  After typing the 1, but
before C-M-i, the line reads:

    f.1

Point is now in LSP position (:line 6 :character 7).  After C-M-i, the
interaction with the server is:

    [client-request] (id:6) Wed Mar 22 10:17:53 2023:
    (:jsonrpc "2.0" :id 6 :method "textDocument/completion" :params
              (:textDocument (:uri "file:///tmp/tmp.wLa6UWw1Nf/src/lib.rs")
               :position (:line 6 :character 7)
               :context (:triggerKind 1)))
    [server-reply] (id:6) Wed Mar 22 10:17:53 2023:
    (:jsonrpc "2.0" :id 6 :result
              (:isIncomplete t :items
                             [(:label "0" :kind 5 :detail "u32" :filterText "0"
                                          :textEdit (:range (:start (:line 6 :character 7)
                                                             :end (:line 6 :character 7))
                                                     :newText "0"))
                              (:label "1" :kind 5 :detail "u32" :filterText "1"
                                          :textEdit (:range (:start (:line 6 :character 7)
                                                             :end (:line 6 :character 7))
                                                     :newText "1"))

   (some elements elided for readability)

Which means the server is offering to _insert_ an _additional_ '0', '1'
etc at position 7.  

Emacs/Eglot is not doing the right thing, but I don't think the server
is doing the right thing either.

Probably the server should be saying "I don't have completions for this
position given my current view of the document".  Maybe this could be
reported to the rust-analyzer people for their input.

However, given this "faulty" server exchange, I'm inclined to say
completion-at-point should offer to insert '0','1', and other
completions, and not immediately insert the "1".

João