From c718d68390e0fa29d391dfeeefbaa22ddd15b3d1 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 28 Jun 2026 00:59:38 +0200 Subject: [PATCH] fix(lsp): rank Go sole-implementer interface resolution at 0.95 For a call through an interface with exactly one implementer (s.Speak() where Speaker is implemented only by Dog), go_lsp emitted both lsp_interface_resolve -> Dog.Speak at 0.90 and lsp_type_dispatch -> Speaker.Speak at 0.95. The join keeps the highest-confidence resolution, so type_dispatch (the interface-method node) always shadowed the concrete sole-implementer resolution. A sole-implementer dispatch is unambiguous; rank it 0.95 so the concrete Type.method wins for that call site. go_py LSP strategy reproductions 15->16. Signed-off-by: Martin Vogel --- internal/cbm/lsp/go_lsp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/cbm/lsp/go_lsp.c b/internal/cbm/lsp/go_lsp.c index 798dcf0cc..6090b8830 100644 --- a/internal/cbm/lsp/go_lsp.c +++ b/internal/cbm/lsp/go_lsp.c @@ -1222,8 +1222,13 @@ static void resolve_calls_in_node(GoLSPContext* ctx, TSNode node) { const CBMRegisteredFunc* concrete_method = cbm_registry_lookup_method(ctx->registry, sole_impl_qn, field_name); if (concrete_method) { + // Sole-implementer interface dispatch is an unambiguous + // resolution (exactly one concrete method); rank it at least + // as high as a direct type dispatch (0.95) so the concrete + // `Type.method` wins over the interface-method type_dispatch + // for the same call site. emit_resolved_call(ctx, concrete_method->qualified_name, - "lsp_interface_resolve", 0.90f); + "lsp_interface_resolve", 0.95f); goto recurse; } }