.trim().to_string() stays ref String, process::run rejects it as Vec[String] (NK1102)Open and answer this issue on GitHub.
decision · opened 2026-10-25 · updated 2026-10-29 · 1 comment
Part of #847 (found by step 2). Reproduced on 0.0.1222.
Probe.
use std::process
fn main() throws {
let a = " x ".trim().to_string()
let o = process::run("echo", [a])
println(o.stdout)
}
nikaia run gives NK1102: process::run expects args to be Vec[String], but you're passing Vec[ref String]. .trim().clone() is accepted.
Why it is a defect. to_string() names an owned String; its result must not stay a ref. Either to_string on a ref String returns ref String (wrong), or the list literal [a] takes the type of the view it came from.
To build.
nikaia check on a variant with let b: String = a).to_string() yields String.tests/compiler/tests/to_string_owned.nika with the probe; delete any .clone() workaround in scripts/agent.nika that exists because of this.The same defect, reached through the checker: .to_string() of a view keeps the view’s type when it stands in a tuple literal, but not in a plain let or a list literal.
Probe (nikaia run p.nika):
comptime A: ref String = "a"
fn f(s: ref String) -> Vec[(String, String)] {
return [(s.to_string(), "b")] // NK1104: Vec[(ref String, String)]
}
fn h() -> (String, String) {
return (A.to_string(), "b") // NK1104: (ref String, String)
}
fn k() -> Vec[String] {
return [A.to_string()] // passes
}
fn g() -> Vec[(String, String)] {
return [(A.clone(), "b")] // passes
}
fn main() {}
The expected result is that all four pass, since to_string() gives text of its own. This comes up in rs2nika drafts: every (CONST.to_string(), ..) pair the converter writes is refused.
To build (in addition to the list above):
x.to_string() with x: ref String is typed String (checker: tuple literal element types).tests/compiler/.Generated by Claude Code