Issue #1192: Check: a field of a ref T? from another package, unwrapped past a jump, is NK1245

Open and answer this issue on GitHub.

ready · opened 2026-11-02 · updated 2026-11-02 · 0 comments

Found by B1183/B1191 (bug lane). A program that unwraps a ref T? handed back by a function of another package, past a jump, cannot read a field of it: the checker gives NK1245. The same function declared -> ref T (no ?) works.

Probe

Package q, src/main.nika:

use std::collections

pub struct Held { pub n: i64 }
pub struct Box2 { pub m: collections::BTreeMap[String, Held], pub plain: Held }

pub fn held_of(b: ref Box2, k: String) -> ref Held? {
	let h = b.m[k] ?? return null
	return h
}

pub fn plain_of(b: ref Box2) -> ref Held { return b.plain }

fn main() {}

tests/probe.nika:

use std::collections
use q

fn main() {
	let mut m: collections::BTreeMap[String, q::Held] = collections::BTreeMap()
	m.insert("a", q::Held { n: 4 })
	let b = q::Box2 { m: m, plain: q::Held { n: 5 } }
	let p = q::plain_of(b)
	println(f"{p.n}")
	let h = q::held_of(b, "a") ?? return
	println(f"{h.n}")
}

Expected 5 then 4. Instead nikaia test --project q refuses:

error[NK1245]: The compiler can't tell what type `h.n` is.
   --> tests/probe.nika:11:2

p.n (from -> ref Held) is typed; only the unwrapped ref Held? of the dependency is not.

To build

  1. Find where a dependency’s function result ref T? is typed for the caller (the ledger’s signature read back across the package boundary) and why the unwrapped ref T loses its struct type (Ty::Unknown), while ref T keeps it.
  2. Fix it in the checker (crates/nikaia-std/src/tools/check_*.nika).
  3. Test: a tests/compiler program that reads a field of a ref T? from a pub fn in tests/compiler/src/ (use compiler_tests), unwrapped with ?? return, with its .stdout.

Generated by Claude Code

Back to Open Issues