LSP icon indicating copy to clipboard operation
LSP copied to clipboard

Importing types via auto-complete sometimes doesn't import the type

Open LPGhatguy opened this issue 8 months ago • 6 comments

Accepting a completion that imports a type or trait sometimes accepts the completion but does not add the import for the type to the top of the file.

For example, accepting this completion:

Image

...will sometimes not add the use std::collections::HashMap; to the top of the file. When this happens, it causes compilation to fail and I have to retry the completion or manually import the type.

Are there diagnostics available for this happening? What should I look for? My coworkers and friends using VS Code don't have this category of problem.

LPGhatguy avatar Aug 17 '25 04:08 LPGhatguy

Sometimes? So not 100% reproducible?

If you can reproduce then it would help to see the LSP Logs (accessible when right clicking the panel icon in the lower-left corner)

rchl avatar Sep 03 '25 20:09 rchl

I can reproduce it by typing let h: HashMap| = Default::default() (where | denotes the cursor position) and hitting enter on the HashMap completion.

LSP Log:

:: [00:04:40.654] --> rust-analyzer textDocument/documentHighlight (246): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 18}}
:: [00:04:40.656] --> rust-analyzer textDocument/diagnostic (247): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:40.656] --> rust-analyzer textDocument/codeAction (248): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 18}, 'end': {'line': 1, 'character': 18}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:40.656] <<< rust-analyzer (246) (duration: 1ms): None
:: [00:04:40.657] <<< rust-analyzer (247) (duration: 1ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:40.709] <<< rust-analyzer (248) (duration: 53ms): []
:: [00:04:41.674] --> rust-analyzer textDocument/documentHighlight (249): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 5}}
:: [00:04:41.676] --> rust-analyzer textDocument/diagnostic (250): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:41.676] --> rust-analyzer textDocument/codeAction (251): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 5}, 'end': {'line': 1, 'character': 17}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:41.676] <<< rust-analyzer (249) (duration: 2ms): [{'range': {'start': {'line': 1, 'character': 5}, 'end': {'line': 1, 'character': 6}}}]
:: [00:04:41.692] <<< rust-analyzer (250) (duration: 15ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:41.697] <<< rust-analyzer (251) (duration: 20ms): [{'title': 'Rename unused h to _h', 'kind': 'quickfix', 'edit': {'documentChanges': [{'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 71}, 'edits': [{'range': {'start': {'line': 1, 'character': 5}, 'end': {'line': 1, 'character': 6}}, 'newText': '_h'}]}]}}, {'title': 'Extract into variable', 'kind': 'refactor.extract', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 5}, 'end': {'line': 1, 'character': 17}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'extract_variable:RefactorExtract:1:', 'version': 71}}, {'title': 'Extract into function', 'kind': 'refactor.extract', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 5}, 'end': {'line': 1, 'character': 17}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'extract_function:RefactorExtract:2:', 'version': 71}}]
:: [00:04:42.387] --> rust-analyzer textDocument/documentHighlight (252): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 7}}
:: [00:04:42.388] --> rust-analyzer textDocument/diagnostic (253): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:42.388] --> rust-analyzer textDocument/codeAction (254): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 17}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:42.389] <<< rust-analyzer (252) (duration: 1ms): None
:: [00:04:42.389] <<< rust-analyzer (253) (duration: 0ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:42.395] <<< rust-analyzer (254) (duration: 6ms): [{'title': 'Extract type as type alias', 'kind': 'refactor.extract', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 17}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'extract_type_alias:RefactorExtract:0:', 'version': 71}}]
:: [00:04:42.822]  -> rust-analyzer textDocument/didChange: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 72}, 'contentChanges': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 17}}, 'rangeLength': 10, 'text': ''}]}
:: [00:04:42.822] --> rust-analyzer textDocument/codeLens (255): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:42.825] --> rust-analyzer textDocument/diagnostic (256): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:42.826] --> rust-analyzer textDocument/documentHighlight (257): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 7}}
:: [00:04:42.826] <-- rust-analyzer workspace/semanticTokens/refresh (158): None
:: [00:04:42.826] >>> rust-analyzer (158) (duration: 0ms): None
:: [00:04:42.827] <-- rust-analyzer workspace/codeLens/refresh (159): None
:: [00:04:42.827] >>> rust-analyzer (159) (duration: 0ms): None
:: [00:04:42.827] --> rust-analyzer textDocument/codeLens (258): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:42.827] <-- rust-analyzer workspace/inlayHint/refresh (160): None
:: [00:04:42.827] >>> rust-analyzer (160) (duration: 0ms): None
:: [00:04:42.828] <<< rust-analyzer (255) (duration: 5ms): []
:: [00:04:42.829] <<< rust-analyzer (257) (duration: 2ms): None
:: [00:04:42.829] <<< rust-analyzer (258) (duration: 2ms): []
:: [00:04:42.859] <<< rust-analyzer (256) (duration: 34ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'severity': 1, 'code': 'syntax-error', 'codeDescription': {'href': 'https://doc.rust-lang.org/stable/reference/'}, 'source': 'rust-analyzer', 'message': 'Syntax Error: missing type'}]}
:: [00:04:42.862] --> rust-analyzer textDocument/diagnostic (259): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:42.862] --> rust-analyzer textDocument/codeAction (260): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'context': {'diagnostics': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'severity': 1, 'code': 'syntax-error', 'codeDescription': {'href': 'https://doc.rust-lang.org/stable/reference/'}, 'source': 'rust-analyzer', 'message': 'Syntax Error: missing type'}], 'triggerKind': 2}}
:: [00:04:42.863] <<< rust-analyzer (260) (duration: 0ms): []
:: [00:04:42.863] <<< rust-analyzer (259) (duration: 1ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'severity': 1, 'code': 'syntax-error', 'codeDescription': {'href': 'https://doc.rust-lang.org/stable/reference/'}, 'source': 'rust-analyzer', 'message': 'Syntax Error: missing type'}]}
:: [00:04:42.955]  -> rust-analyzer textDocument/didChange: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 73}, 'contentChanges': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'rangeLength': 0, 'text': ' '}]}
:: [00:04:42.956] --> rust-analyzer textDocument/completion (261): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 8}}
:: [00:04:42.990] --> rust-analyzer textDocument/diagnostic (262): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:42.991] <-- rust-analyzer workspace/semanticTokens/refresh (161): None
:: [00:04:42.991] >>> rust-analyzer (161) (duration: 0ms): None
:: [00:04:43.003] <-- rust-analyzer workspace/codeLens/refresh (162): None
:: [00:04:43.003] >>> rust-analyzer (162) (duration: 0ms): None
:: [00:04:43.004] --> rust-analyzer textDocument/codeLens (263): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:43.004] <-- rust-analyzer workspace/inlayHint/refresh (163): None
:: [00:04:43.004] >>> rust-analyzer (163) (duration: 0ms): None
:: [00:04:43.005] <<< rust-analyzer (261) (duration: 49ms): <params with 54862 characters>
:: [00:04:43.007] <<< rust-analyzer (262) (duration: 16ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'severity': 1, 'code': 'syntax-error', 'codeDescription': {'href': 'https://doc.rust-lang.org/stable/reference/'}, 'source': 'rust-analyzer', 'message': 'Syntax Error: missing type'}]}
:: [00:04:43.012] --> rust-analyzer textDocument/diagnostic (264): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:43.012] --> rust-analyzer textDocument/codeAction (265): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 8}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:43.013] <<< rust-analyzer (263) (duration: 8ms): []
:: [00:04:43.047] <<< rust-analyzer (264) (duration: 35ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 7}}, 'severity': 1, 'code': 'syntax-error', 'codeDescription': {'href': 'https://doc.rust-lang.org/stable/reference/'}, 'source': 'rust-analyzer', 'message': 'Syntax Error: missing type'}]}
:: [00:04:43.061] <<< rust-analyzer (265) (duration: 49ms): []
:: [00:04:43.205] --> rust-analyzer textDocument/codeLens (266): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:43.206] <<< rust-analyzer (266) (duration: 0ms): []
:: [00:04:43.274] --> rust-analyzer textDocument/documentHighlight (267): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 8}}
:: [00:04:43.275] <<< rust-analyzer (267) (duration: 0ms): None
:: [00:04:43.660]  -> rust-analyzer textDocument/didChange: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 74}, 'contentChanges': [{'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 8}}, 'rangeLength': 0, 'text': 'H'}]}
:: [00:04:43.660] --> rust-analyzer textDocument/completion (268): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 9}}
:: [00:04:43.682] --> rust-analyzer textDocument/diagnostic (269): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:43.683] <-- rust-analyzer workspace/semanticTokens/refresh (164): None
:: [00:04:43.683] >>> rust-analyzer (164) (duration: 0ms): None
:: [00:04:43.720] <-- rust-analyzer workspace/codeLens/refresh (165): None
:: [00:04:43.720] >>> rust-analyzer (165) (duration: 0ms): None
:: [00:04:43.720] --> rust-analyzer textDocument/codeLens (270): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:43.720] <-- rust-analyzer workspace/inlayHint/refresh (166): None
:: [00:04:43.720] >>> rust-analyzer (166) (duration: 0ms): None
:: [00:04:43.721] <<< rust-analyzer (268) (duration: 60ms): <params with 57475 characters>
:: [00:04:43.723] <<< rust-analyzer (269) (duration: 41ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:43.750] --> rust-analyzer textDocument/diagnostic (271): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:43.750] --> rust-analyzer textDocument/codeAction (272): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 9}, 'end': {'line': 1, 'character': 9}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:43.751] <<< rust-analyzer (270) (duration: 30ms): []
:: [00:04:43.796] <<< rust-analyzer (271) (duration: 45ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:43.800] <<< rust-analyzer (272) (duration: 50ms): [{'title': 'Generate constant', 'kind': 'quickfix', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 9}, 'end': {'line': 1, 'character': 9}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'generate_constant:QuickFix:0:', 'version': 74}}]
:: [00:04:43.850]  -> rust-analyzer textDocument/didChange: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 75}, 'contentChanges': [{'range': {'start': {'line': 1, 'character': 9}, 'end': {'line': 1, 'character': 9}}, 'rangeLength': 0, 'text': 'a'}]}
:: [00:04:43.850] --> rust-analyzer textDocument/completion (273): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 10}}
:: [00:04:43.878] --> rust-analyzer textDocument/diagnostic (274): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:43.879] <-- rust-analyzer workspace/semanticTokens/refresh (167): None
:: [00:04:43.879] >>> rust-analyzer (167) (duration: 0ms): None
:: [00:04:43.880] <-- rust-analyzer workspace/codeLens/refresh (168): None
:: [00:04:43.880] >>> rust-analyzer (168) (duration: 0ms): None
:: [00:04:43.881] --> rust-analyzer textDocument/codeLens (275): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:43.881] <-- rust-analyzer workspace/inlayHint/refresh (169): None
:: [00:04:43.881] >>> rust-analyzer (169) (duration: 0ms): None
:: [00:04:43.881] <<< rust-analyzer (273) (duration: 30ms): <params with 57788 characters>
:: [00:04:43.897] <<< rust-analyzer (274) (duration: 18ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:43.901] --> rust-analyzer textDocument/diagnostic (276): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:43.902] --> rust-analyzer textDocument/codeAction (277): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 10}, 'end': {'line': 1, 'character': 10}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:43.918] <<< rust-analyzer (275) (duration: 37ms): []
:: [00:04:43.945] <<< rust-analyzer (276) (duration: 43ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:43.949] <<< rust-analyzer (277) (duration: 47ms): []
:: [00:04:44.150] --> rust-analyzer textDocument/codeLens (278): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:44.151] --> rust-analyzer textDocument/documentHighlight (279): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 10}}
:: [00:04:44.151] <<< rust-analyzer (278) (duration: 0ms): []
:: [00:04:44.163] <<< rust-analyzer (279) (duration: 12ms): None
:: [00:04:44.929] --> rust-analyzer completionItem/resolve (280): {'label': 'HashMap<…>', 'labelDetails': {'detail': '(use std::collections::HashMap)', 'description': 'HashMap<{unknown}, {unknown}, {unknown}>'}, 'kind': 22, 'sortText': '7ffffffb', 'filterText': 'HashMap', 'insertTextFormat': 2, 'textEdit': {'newText': 'HashMap<$0>', 'insert': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 10}}, 'replace': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 10}}}, 'data': {'position': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 10}}, 'imports': [{'full_import_path': 'std::collections::HashMap'}], 'version': 75, 'for_ref': False, 'hash': 'mm36QqldsBsu0Cbb6owvDZ8T8q8='}}
:: [00:04:44.933]  -> rust-analyzer textDocument/didChange: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'version': 77}, 'contentChanges': [{'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 10}}, 'rangeLength': 2, 'text': ''}, {'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 8}}, 'rangeLength': 0, 'text': 'HashMap<>'}]}
:: [00:04:44.933] --> rust-analyzer textDocument/signatureHelp (281): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 16}, 'context': {'triggerKind': <SignatureHelpTriggerKind.TriggerCharacter: 2>, 'isRetrigger': False, 'triggerCharacter': '<'}}
:: [00:04:44.934] --> rust-analyzer textDocument/completion (282): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 16}}
:: [00:04:44.976] --> rust-analyzer textDocument/diagnostic (283): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:44.976] <-- rust-analyzer workspace/semanticTokens/refresh (170): None
:: [00:04:44.976] >>> rust-analyzer (170) (duration: 0ms): None
:: [00:04:44.996] <-- rust-analyzer workspace/codeLens/refresh (171): None
:: [00:04:44.996] >>> rust-analyzer (171) (duration: 0ms): None
:: [00:04:44.997] --> rust-analyzer textDocument/codeLens (284): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:44.997] <-- rust-analyzer workspace/inlayHint/refresh (172): None
:: [00:04:44.997] >>> rust-analyzer (172) (duration: 0ms): None
:: [00:04:45.000] <<< rust-analyzer (281) (duration: 67ms): None
:: [00:04:45.000] <<< rust-analyzer (282) (duration: 66ms): <params with 55367 characters>
:: [00:04:45.017] <<< rust-analyzer (280) (duration: 88ms): {'label': 'HashMap<…>', 'labelDetails': {'detail': '(use std::collections::HashMap)', 'description': 'HashMap<{unknown}, {unknown}, {unknown}>'}, 'kind': 22, 'sortText': '7ffffffb', 'filterText': 'HashMap', 'insertTextFormat': 2, 'textEdit': {'newText': 'HashMap<$0>', 'insert': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 10}}, 'replace': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 10}}}}
:: [00:04:45.017] <<< rust-analyzer (283) (duration: 41ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:45.050] --> rust-analyzer textDocument/diagnostic (285): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:45.050] --> rust-analyzer textDocument/codeAction (286): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 16}, 'end': {'line': 1, 'character': 16}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [00:04:45.051] <<< rust-analyzer (284) (duration: 53ms): []
:: [00:04:45.096] <<< rust-analyzer (285) (duration: 46ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:45.100] <<< rust-analyzer (286) (duration: 50ms): [{'title': 'Import `std::collections::HashMap`', 'kind': 'quickfix', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 16}, 'end': {'line': 1, 'character': 16}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'auto_import:QuickFix:0:', 'version': 77}}, {'title': 'Qualify as `std::collections::HashMap`', 'kind': 'quickfix', 'data': {'codeActionParams': {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 16}, 'end': {'line': 1, 'character': 16}}, 'context': {'diagnostics': [], 'triggerKind': 2}}, 'id': 'qualify_path:QuickFix:1:', 'version': 77}}]
:: [00:04:45.231] --> rust-analyzer textDocument/codeLens (287): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:45.232] <<< rust-analyzer (287) (duration: 0ms): []
:: [00:04:45.250] --> rust-analyzer textDocument/documentHighlight (288): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'position': {'line': 1, 'character': 16}}
:: [00:04:45.285] <<< rust-analyzer (288) (duration: 34ms): None
:: [00:04:46.837]  -> rust-analyzer textDocument/didSave: {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:46.939] <-- rust-analyzer window/workDoneProgress/create (173): {'token': 'rust-analyzer/flycheck/0'}
:: [00:04:46.939] >>> rust-analyzer (173) (duration: 0ms): None
:: [00:04:46.939] <-  rust-analyzer $/progress: {'token': 'rust-analyzer/flycheck/0', 'value': {'kind': 'begin', 'title': 'cargo clippy', 'cancellable': True}}
:: [00:04:47.050] <-  rust-analyzer textDocument/publishDiagnostics: {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'diagnostics': [{'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 15}}, 'severity': 1, 'code': 'E0412', 'codeDescription': {'href': 'https://doc.rust-lang.org/error-index.html#E0412'}, 'source': 'rustc', 'message': 'cannot find type `HashMap` in this scope\nnot found in this scope', 'relatedInformation': [{'location': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'range': {'start': {'line': 0, 'character': 0}, 'end': {'line': 0, 'character': 0}}}, 'message': 'consider importing this struct: `use std::collections::HashMap;\n\n`'}], 'data': {'rendered': 'error[E0412]: cannot find type `HashMap` in this scope\n --> src/main.rs:2:9\n  |\n2 |     let h: HashMap<> = Default::default();\n  |            ^^^^^^^ not found in this scope\n  |\nhelp: consider importing this struct\n  |\n1 + use std::collections::HashMap;\n  |\n\n'}}, {'range': {'start': {'line': 0, 'character': 0}, 'end': {'line': 0, 'character': 0}}, 'severity': 4, 'code': 'E0412', 'codeDescription': {'href': 'https://doc.rust-lang.org/error-index.html#E0412'}, 'source': 'rustc', 'message': 'consider importing this struct: `use std::collections::HashMap;\n\n`', 'relatedInformation': [{'location': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs', 'range': {'start': {'line': 1, 'character': 8}, 'end': {'line': 1, 'character': 15}}}, 'message': 'original diagnostic'}]}], 'version': 77}
:: [00:04:47.073] <-  rust-analyzer $/progress: {'token': 'rust-analyzer/flycheck/0', 'value': {'kind': 'end'}}
:: [00:04:51.866] --> rust-analyzer textDocument/foldingRange (289): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}}
:: [00:04:51.889] --> rust-analyzer textDocument/diagnostic (290): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'identifier': 'rust-analyzer', 'previousResultId': 'rust-analyzer'}
:: [00:04:51.889] --> rust-analyzer textDocument/codeAction (291): {'textDocument': {'uri': 'file:///tmp/tmp.T2DMBiber5/src/main.rs'}, 'range': {'start': {'line': 1, 'character': 16}, 'end': {'line': 1, 'character': 16}}, 'context': {'diagnostics': [], 'triggerKind': 1, 'only': [<CodeActionKind.Refactor: 'refactor'>, <CodeActionKind.Source: 'source'>]}}
:: [00:04:51.890] <<< rust-analyzer (289) (duration: 23ms): [{'startLine': 0, 'startCharacter': 10, 'endLine': 4, 'endCharacter': 1}]
:: [00:04:51.890] <<< rust-analyzer (290) (duration: 1ms): {'kind': 'full', 'resultId': 'rust-analyzer', 'items': []}
:: [00:04:51.896] <<< rust-analyzer (291) (duration: 6ms): []

T0mstone avatar Sep 03 '25 22:09 T0mstone

This is likely due to us not resolving the completion BEFORE applying it. We start resolving just before applying the completion but due to ST limitations (no notifications on or before completion selection) we can't wait for it to get resolved before completion is applied. That makes rust-analyzer not return the edit that adds an import since I guess it doesn't see the original document state anymore.

Related issue: https://github.com/sublimehq/sublime_text/issues/3298

rchl avatar Sep 04 '25 09:09 rchl

Actually, perhaps this is a case that we can handle since it's a slightly different case. I will move it to LSP repo and treat like a bug.

rchl avatar Sep 04 '25 09:09 rchl

After spending time to debug this. I have concluded that this is a bug in rust-analyzer.

These issues are recent, and relevant. https://github.com/rust-lang/rust-analyzer/discussions/19998 https://github.com/rust-lang/rust-analyzer/issues/19401

It would be good to share what these foundings there as well.

predragnikolic avatar Sep 05 '25 20:09 predragnikolic

My response from https://github.com/sublimelsp/LSP/pull/2633#issuecomment-3259681924:

Is there a new completion request triggered automatically when those <...> are inserted? Asking because a new request would likely invalidate the data needed to resolve completion from the previous request. But then I would still not call it a rust analyzer bug but an issue with editor resolving completion too late which #2632 is trying to address.

rchl avatar Sep 06 '25 08:09 rchl