Open and answer this issue on GitHub.
decision · opened 2026-10-31 · updated 2026-10-31 · 1 comment
#997 types an untyped lambda by its first use, but only by its call arguments. Should that typing also take a function field the lambda is put into?
struct H { f: fn(i64) -> i64 }
fn main() {
let g = fn(x) { 5 }
let h = H { f: g }
print(h.f(1))
}
Today, after #1045 (fc3e3377), this program is refused NK1245: no type is known for x. The same lambda handed straight to a call argument, apply(g, 1), runs. A body that uses x (x + 1) also runs, because the body types x.
H { f: g } gives g the type fn(i64) -> i64, just as a parameter of that type does. This is one more place in #997’s typing by use (check_core_stmt / places_stored). The rule reads: “an untyped lambda takes its type from the first place it is handed to: a call argument or a field of a known function type.”fn(x: i64) { 5 }). The refusal names the parameter. The rule stays smaller: only calls type a lambda.Option 1. A struct literal is a place with a declared type, just like a parameter. Treating the two differently is a surprise, and the error appears far from where the type is plainly given. The cost is small: one test, plus one sentence in the rule of Part I for #997.
let lambda by its first usetests/compiler/tests/ with row b of #1045 (fn(x) { 5 } into H { f: g }) printing 5Raised by brief b1045 (report docs/briefs/b1045-let-lambda-fn-field.md.report.md).
Generated by Claude Code
A related case, found while building the resume in scripts/agent.nika (3cfed755). It is the same question asked of a collection literal: does an untyped let take its type from its first use?
use std::process
fn main() throws {
let x = "v"
let env = [("A", x.clone())]
let r = process::run("true", []; env: env)
print(f"{r.code}")
}
This gives NK1106: The option env of process::run takes Vec[(String, String)], but you're passing Vec[(ref String, String)]. Written inline at the call, the same literal is accepted. If the decision here is “typing by first use”, it should probably cover a literal bound by let as well as a lambda.
Generated by Claude Code