Skip to content

refactor(infer): delete receiver.rs — the CST path is the only resolution path#205

Merged
Hessesian merged 3 commits into
refactor/unified-resolutionfrom
refactor/cst-resolution-s8
Jul 4, 2026
Merged

refactor(infer): delete receiver.rs — the CST path is the only resolution path#205
Hessesian merged 3 commits into
refactor/unified-resolutionfrom
refactor/cst-resolution-s8

Conversation

@Hessesian

Copy link
Copy Markdown
Owner

Summary

Task 8, the finale of the CST lambda-triad collapse: receiver.rs (518 lines) is deleted. Net −783 lines. Every lambda-typing question — it, this, named params, completion scope — now resolves through one CST path; the text-expression inference module and all of its helpers are gone. Task 9's sweep (lambda_receiver_type_named_arg_ml, dead helpers/constants) is fully absorbed.

The two problems that gated the deletion

  • Walk scopes on nodes (commit 1): Task 7's ancestor walk resolved each enclosing lambda's it_type by slicing before-brace text into lambda_receiver_type_from_context. lambda_scope_info now resolves from the lambda_literal node via the same cst_lambda_param_type_at the innermost path uses; before_brace survives only to build the display label.
  • Inner-call callee gap: the reason it_type_at_lambda kept a text heuristic was that the node path didn't unwrap a one-level inner call_expression callee. Two minimal unwraps (NodeExt::call_fn_and_qualifier, resolve_callee_chain) close it at root — and subsumed a pre-existing hand-rolled unwrap in lambda_this_ctx, which is deleted. Decoys (trailing_lambda_it_infer_at_cursor, it_element_type_with_call_args) verified RED without the heuristic, GREEN via the node path, assertions untouched.

Also in here

  • EOF-cursor fix (Copilot finding on refactor(completion): rewrite lambda scope-context onto the CST ancestor-walk #202): cursor_node_at used str::lines(), which drops the final empty line of \n-terminated content — a cursor at EOF returned None and emptied the completion scope stack. Fixed with a pinning test (it_resolves_on_trailing_empty_line_at_eof).
  • A nullability truth-telling: stdlib_let_generic_param_not_leaked now expects Long? — the receiver is a plain .let on Long?, so it genuinely is Long?; the old Long was the text heuristic silently stripping nullability. Reviewed and ruled correct per Kotlin semantics.
  • Moves, not rewrites: uppercase_dotted_type_prefix → chain.rs, resolve_call_params + fun_trailing_lambda_this_type → cst_lambda.rs (bodies byte-identical). ItTypeAtLambda and LambdaParamKind::This deleted — the collapse removed type ceremony too, not just text.
  • Test policy: 25 text-heuristic unit tests converted to prove the production CST path; 10 deleted with per-test reasons (each left an in-place pointer to its surviving CST twin).

Verification

  • cargo test --bin kmp-lsp1433 passed, 0 failed (1442 − 10 converted-away + 1 new). cargo clippy -- -D warnings clean.
  • Every deleted function verified at zero live references (Serena find_referencing_symbols + -D dead-code gate).
  • Task-scoped review: Approved, no Critical/Important; the assertion change adjudicated against Kotlin semantics.

Stacked on #204. With this, the lambda-triad collapse (Tasks 1–9) is complete.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the “CST lambda-triad collapse” by removing the text-based lambda receiver inference module and routing it/this/named-param typing and completion scope exclusively through CST-backed resolution, including fixes for trailing-lambda call nesting and EOF cursor positioning.

Changes:

  • Delete src/indexer/infer/receiver.rs and remove its exports/usages, consolidating lambda parameter inference through cst_lambda_param_type_at / CST ancestor-walk paths.
  • Improve callee/receiver-chain unwrapping for f(args) { ... } nesting in both NodeExt and CST chain resolution so call-site inference works without text heuristics.
  • Fix CST cursor lookup at EOF on \n-terminated documents and add a pinning regression test.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/indexer/node_ext.rs Unwrap nested call_expression to recover callee/qualifier for trailing-lambda-with-args shapes.
src/indexer/infer/type_subst.rs Simplify type-arg extraction helpers after receiver.rs deletion.
src/indexer/infer/receiver.rs Deleted: former text-based lambda receiver/type inference path.
src/indexer/infer/mod.rs Remove receiver module from infer module surface.
src/indexer/infer/lambda.rs Remove lambda_type_first_input helper; rely on remaining nth/receiver helpers.
src/indexer/infer/lambda_tests.rs Drop tests tied to removed lambda_type_first_input; adjust to remaining API.
src/indexer/infer/it_this.rs Route it inference through CST-only cst_it_element_type; keep brace-repair flow.
src/indexer/infer/it_this_tests.rs Add EOF trailing-empty-line regression test; convert many tests to CST param typing seam.
src/indexer/infer/cst_lambda.rs Remove text-heuristic fallback plumbing; unify it resolution and fix cursor_node_at EOF handling.
src/indexer/infer/chain.rs Unwrap nested call-expression callee chains; relocate uppercase_dotted_type_prefix.
src/indexer/infer/args.rs Remove dead named-arg text extraction helper previously only used by receiver.rs.
src/indexer/infer/args_tests.rs Remove tests for deleted named-arg text helper.
src/indexer.rs Remove re-exports of deleted receiver/text helpers.
src/indexer_tests.rs Replace text-heuristic direct tests with CST-based cursor-positioned inference assertions.

Comment thread src/indexer/infer/cst_lambda.rs
@Hessesian Hessesian force-pushed the refactor/cst-resolution-s6 branch from 09b0ec8 to b1fa44e Compare July 4, 2026 21:07
Hessesian and others added 3 commits July 4, 2026 23:07
…des; retire the text heuristics

Problem A: the completion ancestor-walk (`lambda_scope_info`) resolved each
enclosing lambda's `it` type by slicing before-brace text and calling
`lambda_receiver_type_from_context`. It now resolves the `lambda_literal` node
directly through `cst_lambda_param_type_at`, the same path the innermost lambda
and named params already use.

Problem B: `f(args) { it }` nests as `outer_call(inner_call, call_suffix{lambda})`,
so the callee lived on the inner call_expression that the CST lookups did not
unwrap. `call_fn_and_qualifier` and `resolve_callee_chain` now unwrap that inner
call, so `loadProduct(a, b) { it }` and `items.mapNotNull(::t) { it }` resolve
through the node path. Decoys `trailing_lambda_it_infer_at_cursor` and
`it_element_type_with_call_args` are RED without the text call, GREEN via nodes.

With both call sites CST-native the text-heuristic family is production-dead, and
the pre-commit clippy gate (-D dead-code) forces its removal here rather than in
the follow-up: `lambda_receiver_type_from_context` + its ~15 internal helpers,
`lambda_receiver_type_named_arg_ml`, `fun_trailing_lambda_it_type`,
`inline_lambda_param_type`, `receiver_aware_params_from_text`, and the orphaned
`extract_named_arg_name`, `lambda_type_first_input`, `first_concrete_type_arg_str`.
`it_type_at_lambda` collapses onto `cst_lambda_param_type_at`; the never-constructed
`LambdaParamKind::This` walk branch and the enum go with it (`cst_it_or_this_type`
→ `cst_it_element_type`); the duplicate inner-call unwrap in `lambda_this_ctx` is
removed. receiver.rs keeps only the three signature utilities the CST resolvers
still call — the follow-up commit relocates them and deletes the file.

Tests: the 25 it_this_tests sites that unit-tested the text heuristic now drive
the production CST resolver via `cst_param_type` (same TestDeps, real lambda
nodes); indexer_tests conversions use full-document + cursor positions. Deleted
as implementation-detail or exact CST twins: trailing_lambda_it_from_fun_def,
trailing_lambda_it_with_method_call_arg, this_in_run_resolves_to_receiver_type,
extract_named_arg_name_test, extract_named_arg_* (args_tests, 5),
lambda_type_first_input_parses_correctly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB
…tion path

Move-don't-rewrite relocation of the three survivors to their sole callers:
`uppercase_dotted_type_prefix` → chain.rs; `fun_trailing_lambda_this_type` and
`resolve_call_params` → cst_lambda.rs. receiver.rs and its `mod` declaration are
gone; every deleted function verified at zero references.

Also folds in the PR #202 review finding: `cursor_node_at` looked the cursor
line up via `str::lines()`, which yields no final empty line for `\n`-terminated
content — a cursor on the trailing empty line (end-of-file, e.g. right after
typing `items.forEach {` + Enter) returned `None`, failing `it` resolution and
the brace-repair gate before they could run, and emptying the completion
lambda-scope stack. The trailing-gap cursor now resolves on the last character
of the last content line (node ends are exclusive), whose node carries the
enclosing context. Pinned by `it_resolves_on_trailing_empty_line_at_eof`
(RED without the fix, GREEN with it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB
… goes tree-wide

The remap used `len() - 1` as a byte column, splitting a multi-byte final
codepoint. Fixing that surfaced a second hole the new pinning test caught:
a trailing comment is a tree-sitter extra attached outside the ERROR node,
so the chain-only gate saw no error and skipped repair for an unclosed
lambda ending in `// note`. The gate now treats any parse error in the tree
as license to repair when no enclosing lambda_literal exists — repair
self-verifies, so over-permission still converges to authoritative None.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJsyQ1UgF8uJYR4HgpxEBB
@Hessesian Hessesian force-pushed the refactor/cst-resolution-s8 branch from 8e1e657 to 7507066 Compare July 4, 2026 21:08
@Hessesian Hessesian changed the base branch from refactor/cst-resolution-s6 to refactor/unified-resolution July 4, 2026 21:08
@Hessesian Hessesian merged commit 0b30b79 into refactor/unified-resolution Jul 4, 2026
@Hessesian Hessesian deleted the refactor/cst-resolution-s8 branch July 4, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants