Skip to content

[]mut T arguments: collection->mutable-slice coercion is missing (blocks #379 buf_out) #604

Description

@ehartford

Summary

With cannot construct a []mut T (mutable slice) argument from a collection. This blocks #379's buf_out fact (memset/explicit_bzero need a []mut u8). Deep-dive below; no code/spec change made pending a scope decision.

Root-cause analysis (deep dive)

[]mut T is a real, live type — TY_SLICE whose d1 field is the mutability flag. The argument compatibility check is correct and strict:

  • src/Sema.w:4426-4429: if exp_k==TY_SLICE and act_k==TY_SLICE: if d1(exp)!=0 and d1(act)==0: return 0 — a []mut parameter demands an actual []mut value; []T does not satisfy it.

The gap is that nothing produces a []mut T value:

  • Slice-creation expressions (a[..], a[0..3]) always build an immutable slice — they emit TY_SLICE with d1=0 regardless of source mutability or expected type (e.g. src/SemaCheck.w:414, range/subscript typing).
  • split_at_mut returns the Vec-specific VecRange[T], not []mut T (src/SemaCheck.w:14790-14811; mutable Vec access is .set()/.get() on VecRange).
  • A bare collection does not coerce: passing var a: [3]u8 to a []mut u8 parameter gives wrong argument type (it also fails for []u8 — only a[..]/a[0..3] coerce, and only to immutable).

Spec intent: this is a compiler bug, not a stale spec

§4.8 (spec lines 2083-2086) explicitly promises the coercion:

"in parameter position, []T and []mut T follow §3.8's borrow mode: the caller's collection coerces to the slice view … for []mut T, the exclusive borrow ends when the callee returns."

So []mut T is the intended model and VecRange is a separate Vec convenience, not a replacement. The compiler is simply missing the collection→[]mut T coercion. Per AGENTS.md ("spec says X works, compiler disagrees ⇒ compiler bug"), this is a bug to fix.

Proposed design

Produce a mutable slice (TY_SLICE d1=1) when, and only when, (a) the expected parameter type is []mut T, (b) the source place is mutable (var binding / mutable field / mutable receiver), and (c) §21.1 exclusivity holds (no overlapping live &T/[]T/[]mut T view of the same place). Touch points:

  1. Slice-creation typing (range/subscript expr → TY_SLICE): thread expected-mutability + source-mutability to set d1. Today it hardcodes d1=0.
  2. Call-argument coercion: accept a mutable collection / a[..] over a mutable source as []mut T (mirror of the existing []T array→slice coercion).
  3. Borrow/exclusivity checker (§21.1): register the exclusive borrow for the argument's lifetime — invalidate overlapping &T/[]T views until the callee returns. This is the subtle part.
  4. MIR/codegen: none expected — a mutable slice has the same (ptr,len) fat-pointer ABI as an immutable one; mutability is compile-time only. (The buf_out wrapper already uses &raw mut s[0], validated to compile.)

Size estimate

Medium. The slice machinery + fat-pointer ABI already work end-to-end for immutable slices, so (1) and (2) are small-to-medium. The risk and most of the effort concentrate in (3) — getting §21.1 exclusivity right for the slice argument (overlap invalidation, NLL end-of-borrow at callee return). Roughly comparable to the buf_in work but reaching into the borrow checker rather than binding-gen. Recommend a dedicated session with adversarial borrow-checker tests.

Once this lands

#379 buf_out is then trivial: add the curated entries (memset out:0:2, explicit_bzero out:0:1, …) to ci_buf_is_mut/ci_buf_count in src/CImport.w. The generator already emits the []mut u8 + &raw mut wrapper; only the overlay config and tests remain.

Status: analysis + design only. Awaiting maintainer decision on whether to fix the coercion (Option A) before resuming #379 buf_out. No []mut T semantics changed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions