Skip to content

Inferred parameter types miss the second of two module functions sharing a leaf name #217

Description

@MelbourneDeveloper

Summary

When two modules export a function with the same leaf name, the inferred
parameter types reach only one of them. The second reports its parameter bare
even though the checker proved it.

Reproduction

module A {
    export fn rate(x) = x + 1 ?: 0
}
module B {
    export fn rate(s) = "${s}!"
}
let v = A::rate(2)
let w = B::rate("hi")
$ osprey mod2.osp --symbols
scratchpad::A::rate -> fn scratchpad::A::rate(x: int) -> int
scratchpad::B::rate -> fn scratchpad::B::rate(s) -> string

B::rate's return type resolves (string), but its parameter stays s where
it should be s: string. With only one rate in the program, both slots fill
correctly — the loss appears only once a second module reuses the leaf name.

Root cause

fill_inferred (crates/osprey-lsp/src/analysis.rs) looks a symbol up by its
QUALIFIED outline name (A::rate), while ProgramTypes::param_types is keyed
by the leaf the checker recorded (rate). One entry answers for both modules,
so the second symbol's parameter lookup misses.

The obvious patch — falling back to the unqualified source_name — is worse
than the gap: two modules exporting rate would then be handed each other's
parameter types, turning a missing annotation into a wrong one. The lookup has
to stay scope-aware.

Scope

Not a regression. On main symbols_json never consulted inference at all, so
every parameter came back bare; this branch fills them and this is the one
shape it does not reach. B::rate is no worse than main, A::rate is
better.

Suggested direction

Infer and fill each module container against its own local Program, then
qualify the resulting names on the way out, rather than filling qualified
symbols from one global ProgramTypes whose keys have already lost the module
scope. Alternatively, key ProgramTypes function entries by qualified name so
the outline's lookup is exact.

Acceptance

  • Both A::rate and B::rate report their proven parameter and return types.
  • A test with two same-leaf module functions of DIFFERENT types asserts neither
    is given the other's — the wrong-answer case must be pinned, not just the
    missing-answer one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions