Issue #993: Two overlap branches that write the same literal file are accepted (NK2104 missing)

Open and answer this issue on GitHub.

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

Part I 8.1.2 (and ADR-292 D3) says two branches that meet on a resource, one of them writing it, are refused with NK2104, and names file(path) as such a resource. With target/fast/nikaia on develop (0.0.1306), this program is accepted:

use std::fs
fn main() throws {
    overlap {
        fs::write("log.txt", fs::Root::Anywhere, "a")
        fs::write("log.txt", fs::Root::Anywhere, "b")
    }
}

nikaia check prints Checked p2.nika. Two branches that both println are refused as expected (“Both touch stdout, and one writes to it.”), so the check runs; the file resource of fs::write is not reached. It is either missing from fs::write’s touches entry, or the literal path argument is not read as named. Compare crates/nikaia-std/src/tools/touch.nika, Reached::might_be_same.

Found while rewriting the website (website/safe/conflicting-actions.html now says plainly that this case is accepted today). The same check carries over to async children and par_iter lambdas (ADR-async-2, ADR-async-4), so it matters for #986.

To build

  1. Find why fs::write with a literal path does not reach file("log.txt") write in the touch walk, and fix it in the compiler (contract entry or argument reading), not in the program.
  2. Test in tests/compiler/tests/: the program above refused with NK2104 naming file(log.txt). A second test with two different literal paths is accepted. A third with a non-literal path is not refused (Part I 8.1.2: a branch the compiler cannot account for).
  3. Check the other fs writers (append, remove, rename, create_dir) for the same gap.

Back to Open Issues