Repository navigation
fix(when): type a when subject from the binding in scope at the when - #335
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Field-chain inference discards the newly available origin URL and can still select an unrelated homonymous root type.
3 open findings
What changed in this PR
Fixes when subject inference to use the local binding in scope at the expression.
Changes:
- Adds scope-aware local type inference with origin tracking.
- Updates plain and field-chain
whensubjects to use it. - Adds regression tests for shadowed and inferred locals.
| File | Description |
|---|---|
src/resolver/infer.rs |
Uses scoped binding inference for chain roots. |
src/indexer/infer/expr_type.rs |
Adds infer_local_type_at. |
src/indexer/infer/cst_symbol.rs |
Adds by-name binding lookup at a CST node. |
src/indexer.rs |
Re-exports the new inference helper. |
src/features/fill_when.rs |
Uses scope-aware subject type inference. |
src/features/fill_when_tests.rs |
Adds diagnostic regressions. |
AGENTS.md |
Documents the new helper. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Hessesian
force-pushed
the
fix/when-subject-through-local-binding
branch
from
October 9, 2026 15:25
fcadf47 to
8b42dc5
Compare
`resolve_declared_type_from_cst` was the one scope-aware declared-type lookup, but it searched a statement list in any order and only read annotations (plus Boolean literals). So for a `when` subject: - a same-named `val` declared *after* the `when` won over the parameter actually in scope, and - an unannotated `val value = pick()` fell through to the file-wide by-name scan, which answered with another function's `value` parameter. Both reported missing branches of the wrong enum. The same applied to the root of a field-chain subject (`when (holder.shade)`). `cst_symbol::local_binding_of(name, point, ..)` is the by-name-at-a-point form of `local_binding_at`, and `infer_local_type_at` turns the binding into a type. `fill_when::analyze_when` and `infer_field_chain_type` now ask it; `resolve_declared_type_from_cst` had no other callers and is deleted. An unannotated subject also carries the file its type was written in, which `analyze_when` uses to resolve the type's members. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tten in Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Hessesian
force-pushed
the
fix/when-subject-through-local-binding
branch
from
October 20, 2026 08:10
b0ed1cd to
11b0d5c
Compare
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Stacked on #334. Review and merge that first; this PR's diff is only the commit on top.
Bug
resolve_declared_type_from_cstwas the one scope-aware declared-type lookup, used forwhensubjects. It searched a statement list in any order and only read annotations (plus Boolean literals), so:The same applied to the root of a field-chain subject (
when (holder.shade)).Fix
cst_symbol::local_binding_of(name, point, bytes): the by-name-at-a-point form oflocal_binding_atfrom fix(resolve): type an identifier from the declaration that binds it at that node #334, for callers that hold a name and a position rather than the identifier node.local_binding_atnow delegates to it.expr_type::infer_local_type_at(name, point, ..): the type that binding states, with the file it was written in.fill_when::analyze_whenandresolver::infer::infer_field_chain_typeask it, then fall back to the same by-name lookups as before.resolve_declared_type_from_cst(116 lines) is deleted. It had exactly these two callers.One deliberate behaviour change beyond scoping: an unannotated subject now carries the file its type was written in, and
analyze_whenuses that file to resolve the type's members, as it already did for field chains.Tests
Three new diagnostics tests in
fill_when_tests.rs, all red before the change with the wrong enum's branches in the message: later-declared local, unannotated local with a same-named parameter in another function, and field-chain root. Existing Boolean-literal and nullable-subject tests still pass through the new path.RUSTFLAGS="-D warnings" cargo test: 2073 unit tests + integration suites pass.cargo clippy --all-targets -- -D warningsclean.Not measured
No Moneta run:
resolution-accuracyexercisesclassify_cursor+resolve_identity, notwhendiagnostics, so it would not see this change. Cost is one scope climb perwhenexpression.Merge-order note
This removes one
resolver::infer::reach fromsrc/features/fill_when.rs. If #333 (the ratchet) merges first, itsresolver::infer::baseline must drop from 7 to 6 when this is rebased; the test will say so.🤖 Generated with Claude Code