# lang-review round 2 findings (2026-07-12, HEAD 76694ad)

r1 の major findings (#807-#816, #822) 修正後の再評価。スコアは
[scores/2026-07-12-r2.json](../scores/2026-07-12-r2.json)。平均 3.0 → 3.36。

## r1 修正の実地確認 (全レビュアー)

- String for-in (#807): 3 回イテレーション・byte 値 yield を確認
- loop+match break/continue (#808): 終了確認 (r=10)
- guard-only match (#809): actionable な compile error
- unknown struct field (#810): located compile error。extra-field も reject (ADR の open hole が閉じた)
- OOB index (#811): Array/Bytes/String すべて trap (silent garbage 消滅)
- parse error 位置 (#816): offending token の実位置 (line:col)、lexer 内部情報なし
- effect op シグネチャ (#813): perform 引数/arity、arm 名 typo、payload 型、resume 型すべて reject
- import 越し effect row (#812): reject + actionable message
- k-convention (#814): 明示 located エラー
- let mut 注釈 (#824): reject
- Bytes::new(n) (#823): length-n zero-fill 動作
- writability: 10/10 タスク、compile error 計 1 回 (r1: 1 回 + silent 故障 2 件 → 0 件)

## 新規 major findings

### M1. 構造的 == が Option/Result の aggregate payload で silent に reference 等価へ落ちる (semantics)

`Some([1,2]) == Some([1,2])` → **false**。`Some((1,2))`、`Some(Some(1))`、
`Ok([1,2])`、`([1,2],0) == ([1,2],0)` (array 入り tuple) も false。
一方 user enum `E::A([1,2])`、struct field、`[[1,2]]`、`Some("ab")` は
正しく structural。builtin generic enum の payload 比較と tuple 要素比較が
再帰 structural-eq を通っていない。**silent wrong value の最悪クラス** → issue 化

### M2. handler replay が観測可能 — handle body の副作用が perform ごとに再実行 (semantics)

`[body-start]` が 2 perform で 3 回 print、`let mut` は count=11 期待が 23、
戻り値まで壊れる (r=17 期待が 29)。cheatsheet の「resume は perform の
続きから」と矛盾。replay 実装 (ADR-0055) の既知特性だが、ドキュメントと
実挙動の乖離 + 値破壊は headline feature の欠陥 → #817 (evidence-passing)
へ集約 + 当面の文書化

### M3. Array::get/set の引数 slot が未検査 (type-soundness)

`Array::get("str", 0)` compile → trap、`Array::get([1,2,3], "x")` compile →
silent garbage。Array::get は要素型推論の special branch を通るため
builtin_first_arg_head / builtin_arg_head_rest の検査を素通りする。
Array::length は reject するので非対称 → issue 化 (bounded fix)

### M4. for-await が未注釈 lambda param 経由で compile → 実行時 trap (concurrency)

`let consume = (s) -> { for await x in s { ... } }; consume(Stream::once(42))`
が compile して `table index is out of bounds` trap。#822 は分類可能ケース
のみ修正。desugar 時の構文的分類で意味が決まる構造自体が ADR-0068
constraint 4 違反 → issue 化 (checker-level 型主導分類 or 未解決時 compile error)

### M5. Stream[T] が Array builtin で観測可能 (concurrency)

`Array::length(Stream::once(41))` / `Array::get(s, 0)` が compile して動く
(Stream は CtNamed で head gate を素通り)。eager Array backing が public
observable になっており、真の stream.read backing への移行で壊れる →
issue 化 (unstable surface の今なら安く塞げる)

### M6. handler op-arm 網羅性が未検査 (type-soundness)

effect {A;B} のうち A だけの handler が compile、B の perform は
unreachable trap。checker は op 集合を知っている (#813 で arm 名 typo は
reject) ので bounded fix → issue 化

### M7. generic struct field の instantiation 未検査 (type-soundness, 既知 ADR 残穴)

`struct Box[T] { v: T }; String::length(Box::{v:1}.v)` compile → garbage。
SStruct/TDStruct に型パラメータ infra が無い。ADR 記載の残穴の現状確認 →
0.3.0 型システム作業で対応 (issue 化)

## 主要 minor findings

- **k-convention 誤診断** (type-soundness): arm payload の単純な余分 binder
  typo (`Log(a, b)` で b 未使用) が k-convention エラーと誤報告される。
  binder が call されている場合のみ k-conv メッセージにすべき → 即修正対象
- **resume() 0 引数 ICE** (type-soundness): `Get() -> Int` に `resume()` で
  compiler 内部 unreachable (診断ゼロ)。checker で resume arity 検査 → 即修正対象
- **#815 残渣** (semantics): `\{Some(1) == Some(1)}` が 1/0 表示 (== over
  builtin enum が boolish 分類されない)。M1 修正と同時に対処
- **or-pattern binding ICE** (semantics, r1 から継続): `A(x) | B(x) => x` が
  `__shadow_4_x` 内部名 leak で crash。実装 or located reject
- **struct literal の field 評価順** (semantics): 宣言順で評価 (record は
  記述順)。記述順に統一すべき
- **診断 1 個制限** (semantics): parse recovery が 2 個目の独立エラーを
  報告しない (vibe diagnostics 経路以外)。checker も最初のエラーで打ち切り
- **未 located の checker エラー**: return mismatch / missing field /
  網羅性 / effect エラーが位置なし。let-annotation mismatch は
  `argument type mismatch for <expr>` と誤カテゴリ + placeholder leak
- **runtime trap に位置情報なし**: div-by-zero / OOB が [crash debug]
  hexdump 付き raw trap。panic message (op/index/length) + dump の env flag 化
- **docs 乖離**: Int range (2^61 が表現可能、wrap 挙動未記載)、String の
  UTF-8 byte 意味論 (substring が codepoint を割る)、宣言セパレータ
  (docs は「comma は parse error」だが実際は通る)、interpolation 2 形式
  (`\(x)` / `\{x}`) の混在
- **stdlib gap**: String→Int parse — 実は `Int::parse(String) -> Option[Int]`
  が builtin として存在していた (#767) が cheatsheet 未記載でレビュアーも
  発見できず (= docs バグとして裏付け)。追調査で overflow 未検査
  (max+1 が silent に範囲外値で Some になる) も発見 → cheatsheet 記載 +
  overflow guard を追加済み。method-bearing trait 不在 (Show が marker +
  namespace fn) は継続
- **concurrency 継続**: replay handler の ~16K perform 上限と固定 global
  region、sendability 規律不在、default backend の untagged i64 (RC cutover
  READY だが未 default)、#626 の Async composition 許容の「final」扱いは
  real-async cutover で再訪と再スコープすべき

## 次アクション

1. M1 / M3 / M4 / M6 と k-conv 誤診断・resume() ICE を issue 化して修正
   (silent wrong value / trap / ICE クラスは即時)
2. M2 は #817 に集約、当面 cheatsheet に replay 特性を明記
3. M5 / M7 / minor 群は 0.3.0 実装項目 (型パラメータ infra、診断 recovery、
   冗長文法削除、@vibe/core 拡充) に紐付け
4. round 3 は上記消化後
