Issue #1207: Lowering: the value m.entry(k).or_insert(v) hands back stays a &mut into the map, so a later use of the map is refused by rustc

Open and answer this issue on GitHub.

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

Found while probing the forms a CDCL(T) solver needs in Nikaia: the e-graph of ADR-270 D13 keeps a signature table (hash-consing, term to id). Probed on target/fast/nikaia at 31e2ea7, language 0.0.1341.

Probe

use std::collections
fn main() {
    let mut t: collections::HashMap[i64, i64] = collections::HashMap()
    let id = t.entry(7).or_insert(3)
    let n = t.len()
    println(f"{id} {n}")
}

nikaia check accepts it; nikaia run fails in rustc: Cannot borrow t as immutable because it is also borrowed as mutable. Expected: 3 1.

id is a let without mut of a value that copies (i64), so in Nikaia it is a number of its own; the lowering keeps it as Rust’s &mut i64 into the map, and every later use of t while id lives is refused. The same with a tuple key (HashMap[(u32, u32, u32), u32]).

To build

  1. A test tests/compiler/tests/a_value_or_insert_hands_back_is_a_copy.nika with the probe and 3 1 as its .stdout.
  2. Where the result of or_insert / or_insert_with is bound by a let without mut, or used as a value, and its type copies, lower it as a copy (*m.entry(k).or_insert(v)). A let mut over it stays a view of the entry (in-place change, as for let mut c = m[k] ?? continue, #816). A type that does not copy: as today, a view while read; check the case with a String value and state in the report what it does.

Back to Open Issues