Skip to content

lsp: goto/hover resolve by syntactic name-scan and can contradict the type checker #245

Description

@0xGeorgii

Follow-up from the comprehensive review of PR #239 (LSP server). Line numbers reference the PR branch at review time.

Severity: major (1-2), minor (3-6) — goto/hover resolve by syntactic name-scan and can contradict what the type checker already resolved. All reproduced with probe binaries against inference-ide on programs that compile with 0 diagnostics.

  1. Free-function call navigates to a same-named struct method (goto_definition.rs:177): struct S { v: i32; fn get(self) -> i32 {...} } + free fn get() -> i32 + return get(); — goto on the callee jumps to S::get (focus 22..25) instead of the free fn (offset 63); hover shows the wrong signature fn get(self) -> i32. The checker resolved the call correctly (CallTarget has receiver_struct=None). Fix: when receiver_struct is None, restrict the by-name search to non-method defs; apply the same fix to callee_signature in hover.rs.
  2. Selective import resolves to the wrong module (goto_definition.rs:193): entry use lib; + use other::{MAX}; + return MAX; with both modules exporting MAX — goto lands in lib.inf. The fallback iterates use directives in source order and returns the first module containing any pub def with that name, never consulting UseDirective::imported_types nor braced. It also "resolves" bare names that were never imported under a brace-free use lib; (a type error).
  3. Hover on the leaf of a qualified type ignores the qualifier (hover.rs:101): hovering the T of lib::T shows the local same-named struct's signature (or a bare name when there is no local T), while goto on the same position correctly lands in lib.inf.
  4. pub use re-export chain not followed for constants (goto_definition.rs:184): entry use mid::{MAX};, mid.inf: pub use lib::{MAX};, lib defines it — clean program, goto returns None. Calls handle re-exports; value defs do not.
  5. Function types render as the checker-internal carrier (type_render.rs:49): hovers/inlays show Function<2, i32> (param COUNT + Display of return kind, from type_info.rs:353-357) despite the module contract promising "the source-like type spelling … never an internal mangled form".
  6. Nit: NavigationTarget.full_range for a local-binding use is just the name ident, while the declaration-site path returns the whole let statement (goto_definition.rs:96) — same logical target, inconsistent POD.

Direction: prefer resolving through the checker's resolution (CallTarget / symbol data) over syntactic scans, follow re-export directives, and consult directive item lists — several of these share that root cause.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglspLanguage Server Protocol

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions