Issue #597: Decision basis: the text-tier walk cannot see that a pattern binding is a view, so a mixed match asks for .clone() where EitherText would do

Open and answer this issue on GitHub.

compiler, decision · opened 2026-10-12 · updated 2026-10-12 · 1 comment

What it is

Text has three representations below, chosen per position by what flows in (ADR-282 D12-D15):

The walk that chooses them, tools/text_tiers.nika (text_tiers::refine, called from the parser), runs before the checker. It has no types: it reads them off the syntax (tier_struct_of, source_of, place_of).

fn f(v: ref Val) -> String {
    return match v {
        Val::Int(n) => int_text(n),   // owned
        Val::Text(t) => t,            // a view: v is lent, so t is a view of its part (Part I 3.4)
        else => "none".clone(),
    }
}

By ADR-282 the result is mixed, so it should be EitherText. The walk does not bind pattern names. An unknown name counts as owned, so it decides String.

Where it comes from, and what needs it now

#562’s analysis, by the session that took #562 (12 Oct). Order decided by the owner the same day:

  1. First #596 fixes the checker, so this case becomes NK1104 at t, naming t.clone(), instead of a rustc error. ADR-282 D13 (“leaves the old refusal and never a wrong program”).
  2. Then #562 fixes the lowering of a mixed match.
  3. Only then this issue: the refusal is an over-refusal. The program is correct by ADR-282 D15 and runs as EitherText without a copy.

Nothing is blocked. A program writes t.clone() and pays a copy it would not need.

Facts (checked on 0.0.854 by the #562 session and in the owner’s round)

Options

  1. Pattern bindings in the walk.
    • The kind of a binding to a text payload is the kind of the scrutinee’s place (place_of).
    • The payload’s type comes from the enum’s declaration, which is syntax: no inference.
    • Each scrutinee form the walk does not cover stays owned. After #596 that is an over-refusal with a .clone() help, never a wrong program.
    • Cost: the third syntax approximation grows.
  2. Every binding of unknown origin counts as “may be a view”.
    • Always safe for the representation.
    • But it makes positions mixed that are owned today, and in a pub function refuses them (NK1104, ADR-282 D22), where they run today.
  3. The tier decision moves after the checker.
    • One source of types: the checker’s, per expression, through the expression ids of ADR-340 (#558, open).
    • views.nika could read the same source.
    • It changes ADR-282 D13 (“runs to a fixpoint … before anything else looks at the program”), the order of the phases, and the self-hosting plan for check and emit (docs/selfhosting-plan.md).

Owed before the owner is asked

Comments

keywan-ghadami, 2026-10-12

State after #596 (0.0.860) and #562 (0.0.861)


Generated by Claude Code

Back to Open Issues