## 背景 #73 で `OpenApiValidationResult::failure([])` を runtime に拒否する実装を入れた (#96)。これにより不正な構築は throw されるが、**型シグネチャ上は依然 `string[]` のまま**で静的検出が効かない。 - `failure(array $errors, ?string $matchedPath = null)` のパラメータは `@param string[] $errors` のため、`failure($maybeEmpty)` は PHPStan に検出されず実行時まで到達する - `errors(): array` の戻り値も `string[]` のため、`Failure` に対して呼んでも PHPStan は「空配列の可能性」を保持し、`errorMessage()` の consumer は静的に non-emptiness を主張できない #73 自体はこの型注釈強化を「PHPStan extended types の導入は別議論」として明示的に scope 外にしていたため、フォローアップとして切る。 ## 提案 PHPStan extended types で `non-empty-array<string>` を導入する: 1. `failure()` のパラメータ: ```php /** @param non-empty-array<string> $errors */ public static function failure(array $errors, ?string $matchedPath = null): self ``` 2. `errors()` の戻り値: 現状 `Failure` 以外でも呼べるため、無条件 `non-empty-array<string>` は嘘になる。選択肢: - **(A) 据え置き** — `string[]` のまま。`errors()` は3 outcome 共通アクセサなので妥当 - **(B) conditional return type** — 呼び出し前に outcome で narrow する形に変更 (大きめの変更) - **(C) 専用アクセサ追加** — `failureErrors(): non-empty-array<string>` を新設し、`Failure` 以外で呼ぶと throw 推奨は **(A) + パラメータのみ強化**。consumer 側で必要なら `assert($result->isValid() === false)` 後に `errors()` を narrow する。 3. PHPStan の baseline / ignore に既存エラーが出る場合は同 PR で修正する (workspace ルール: PHPStan エラーは ignore せず根本修正) ## 受け入れ条件 - [ ] `failure()` のパラメータが `non-empty-array<string>` で注釈されている - [ ] `vendor/bin/phpstan analyse` が pass する (新規 ignore なし) - [ ] 空配列リテラル `failure([])` が PHPStan エラーとして検出される (テスト用に一時的に書いてみて確認) - [ ] 既存の `failure(['...'])` 呼び出し7箇所が PHPStan に通る ## スコープ外 - `errors()` の conditional return type / 専用アクセサ案 ((B), (C)) — 別 issue で議論 - `Success` / `Skipped` ファクトリの引数強化 — そもそも引数を取らないので対象外 ## Refs - Parent issue: #73 - Implementation PR: #96 - PR #96 type-design review: 「Invariant Expression 3/5 — non-empty 不変条件が signature レベルで不可視」
背景
#73 で
OpenApiValidationResult::failure([])を runtime に拒否する実装を入れた (#96)。これにより不正な構築は throw されるが、型シグネチャ上は依然string[]のままで静的検出が効かない。failure(array $errors, ?string $matchedPath = null)のパラメータは@param string[] $errorsのため、failure($maybeEmpty)は PHPStan に検出されず実行時まで到達するerrors(): arrayの戻り値もstring[]のため、Failureに対して呼んでも PHPStan は「空配列の可能性」を保持し、errorMessage()の consumer は静的に non-emptiness を主張できない#73 自体はこの型注釈強化を「PHPStan extended types の導入は別議論」として明示的に scope 外にしていたため、フォローアップとして切る。
提案
PHPStan extended types で
non-empty-array<string>を導入する:failure()のパラメータ:errors()の戻り値: 現状Failure以外でも呼べるため、無条件non-empty-array<string>は嘘になる。選択肢:string[]のまま。errors()は3 outcome 共通アクセサなので妥当failureErrors(): non-empty-array<string>を新設し、Failure以外で呼ぶと throw推奨は (A) + パラメータのみ強化。consumer 側で必要なら
assert($result->isValid() === false)後にerrors()を narrow する。PHPStan の baseline / ignore に既存エラーが出る場合は同 PR で修正する (workspace ルール: PHPStan エラーは ignore せず根本修正)
受け入れ条件
failure()のパラメータがnon-empty-array<string>で注釈されているvendor/bin/phpstan analyseが pass する (新規 ignore なし)failure([])が PHPStan エラーとして検出される (テスト用に一時的に書いてみて確認)failure(['...'])呼び出し7箇所が PHPStan に通るスコープ外
errors()の conditional return type / 専用アクセサ案 ((B), (C)) — 別 issue で議論Success/Skippedファクトリの引数強化 — そもそも引数を取らないので対象外Refs