Issue #900: let mut c = a.clone() of a struct: assigning owned text to c.field is NK1105 (ref String)

Open and answer this issue on GitHub.

ready · opened 2026-10-27 · updated 2026-10-27 · 0 comments

Probe

struct Ctx {
    name: String,
    n: i64,
}

fn main() {
    let a = Ctx { name: "a", n: 1 }
    let mut c = a.clone()
    let t: String = f"x{a.n}"
    c.name = t
    println(f"{a.name} {c.name}")
}

nikaia run refuses it:

error[NK1105]: You're assigning `String` to something that holds `ref String`.
  c.name = t

Expected: the program prints a x1.

What changes the result

So the binding that let mut c = a.clone() makes, untyped, is typed as a view of Ctx, and its fields read as ref String. check_core_call_on_owned hands back the owned type for .clone() of a declared type (check_core_call_on.nika:168). The view must therefore come from the let (check_core_stmt.nika around 550-592: lent_lets, lent_arms_bound, views_meet_owned_text) or from a lent-clone analysis that does not count a write to a field of the binding as a write.

Found while splitting rs2nika_convert into a load step and a pure step, which runs under par_iter (crates/rs2nika/convert/src/main.nika, rs2nika_convert_in). There the binding is written with its type, as every binding in that file is.

To build

  1. A test tests/compiler/tests/a_field_of_an_untyped_clone_takes_owned_text.nika with the probe and its .stdout.
  2. Find where the untyped let mut c = a.clone() becomes a view, and fix it there: a binding whose field is assigned owned text owns its value.

Back to Open Issues