Issue #1057: A non-copy field of an element read, let s = path.last() ?? return null; return s.inner, passes check and fails in rustc (E0507)

Open and answer this issue on GitHub.

ready, wip · opened 2026-10-31 · updated 2026-10-31 · 0 comments


agent: builder model: opus max_turns: 80 budget_usd: 16 — Problem. A field that does not copy, read off a local bound to an element read (let s = path.last() ?? return null) and handed back by value, passes nikaia check and fails in rustc (Cannot move out of s.inner which is behind a shared reference). The whole element handed back is refused since #1044 (920d8608, NK1131 with help …?.clone()); its field is not. Found by b8 (#1044) and probed by the bugs architect on the fast binary at 1e5b0a7c.

Probe

struct Inner { name: String }
struct Item { inner: Inner }
fn last_inner(path: Vec[Item]) -> Inner? {
    let s = path.last() ?? return null
    return s.inner
}
fn main() {
    let xs = [Item { inner: Inner { name: "a" } }, Item { inner: Inner { name: "b" } }]
    let r = last_inner(xs) ?? return
    println(r.name)
}

Rows (same Inner/Item, body of last_inner):

Suspected location. check_core_a_lent_place_given_away, crates/nikaia-std/src/tools/check_core_leaves.nika:117, the Expr::Field arm (:158): place_path gives s.inner with root s, then !state.lent_here(root) (:226) returns, because s is a let with view_of = path.last(), not a lent parameter. The Variable arm (:126-157) already tells such a local (check_core_leaves_list_of_a_read) and refuses through check_core_leaves_an_element_read_given_away.

To build

  1. Row a (and its map form, let s = m.get(k) ?? return null; return s.inner): in the Field arm, when the root is a binding whose view_of is an element read (check_core_leaves_list_of_a_read non-null), keeps holds and the field’s type does_not_copy, refuse NK1131 through check_core_leaves_an_element_read_given_away (what = the field path, help copying the field path with .clone()). Test tests/compiler/tests/a_field_of_an_element_read_handed_back.nika + .stderr (rows a and map form), a_field_of_an_element_read_copied.nika + .stdout (row d). Bug-lane brief b10.
  2. Rows b and c: trace and fix (row b’s base is an Expr::Coalesce; see #1055’s fix for a field of a ?? result). Own brief after step 1.

Rules: docs/briefs/common.part. Report: fields of docs/architect.md, Briefs and reports.


Generated by Claude Code

Back to Open Issues