fix(analyser): pick most-specific overload in scope 🎯#158
Merged
Conversation
Same-scope overload resolution used `rposition`, so a later-registered less-specific overload would shadow an earlier more-specific one. The `locate` stdlib function exposed this: passing a predicate dispatched to the element-equality overload (registered second), which compared the function value against each element and produced "locate did not find anything". `Scope::find_function` now collects every signature-compatible candidate and returns the one not strictly dominated on its parameter signature in the subtype partial order, tie-breaking by latest registration. Variadic overloads are treated as least specific. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
24aa558 to
c12ee66
Compare
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.
Context
Reported via chat:
locate(seq, predicate)was broken — calling it with a function argument errored withlocate did not find anything, even when the predicate matched.The stdlib registers two
locateoverloads with arity 2 (ndc_stdlib/src/sequence.rs):locate(SeqValue, &mut VmCallable)— predicate formlocate(SeqValue, Value)— element-equality form, registered secondScope::find_functionusedrpositionto pick an overload, so the later-registered element-equality form won whenever both matched. When a function value was passed, the analyser bound the call to the wrong overload, which then compared each element to the function value (never equal) and finally errored.Changes
Scope::find_functionnow collects every overload in the scope whose signature accepts the call, then picks the one not strictly dominated by another match's parameter signature in the subtype partial order. Ties resolve to the latest-registered overload, preserving shadow semantics.parameters: None) are treated as the least specific shape, so any concrete overload that also matches dominates them.is_strictly_more_specifichelper that compares two parameter lists pointwise viaStaticType::is_subtype.Scope chain semantics are unchanged: any match in the current scope still stops the walk, so
fn foo(Any)in an inner scope completely shadows the parent, whilefn foo(Int)only shadowsIntcalls.Tests
scope.rscovering same-scope specificity (locate-style and numeric),fn(Any)shadowing,fn(Int)falling through for other arg types, and concrete vs variadic.tests/functional/programs/603_stdlib_seq/012_locate.ndcexercising bothlocateoverloads.🤖 Generated with Claude Code