Skip to content

L38 — Typed validated() array shapes from rules - #294

Open
shuvroroy wants to merge 3 commits into
PHPantom-dev:mainfrom
shuvroroy:feat/typed-validated-array-shapes-from-rules
Open

L38 — Typed validated() array shapes from rules#294
shuvroroy wants to merge 3 commits into
PHPantom-dev:mainfrom
shuvroroy:feat/typed-validated-array-shapes-from-rules

Conversation

@shuvroroy

Copy link
Copy Markdown
Contributor

$request->validated() was declared array and nothing more — no mainstream tool takes it further. The validation rules array is a static type contract, though: it names every key the result can hold and says what each one is. This translates that contract into an array{…} shape instead of leaving it as bare array.

See the commit message for the mechanism (rules→shape translation, optionality rules, the thread-local resolver, the two hook sites). Worth a reviewer's attention:

  • nullable ≠ present. The obvious reading is that nullable guarantees the key with a possibly-null value. I checked against the real validator: ['age' => 'nullable|integer'] validated against [] yields [], not ['age' => null]. So nullable alone leaves the key optional (age?: ?int); only required/present guarantee it. This is pinned by a runtime assertion in examples/laravel/assertions.php so the demo comments can't drift from what Laravel actually does.
  • Two hook sites, not one. The type engine has no single choke point for method-call return types — the text/SubjectExpr path (hover) and the AST/assignment path ($data = …) are genuinely parallel pipelines, and the existing configured_laravel_date_return feature is hooked into both for the same reason. Same pattern here, not duplication for its own sake.
  • Bail-out is deliberate, not partial-credit. A computed rule key, a spread, or any non-literal source abandons the whole shape for plain array. A shape that silently drops a real key would flag valid runtime input as an unknown-key diagnostic — worse than no shape at all.
  • Reuse. rules_in_scope (FormRequest's own rules, else the nearest preceding validate()) is factored out of L37's completion path so this feature and L37 share one definition instead of two that could quietly disagree about which rules apply at a given cursor.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, examples/)
  • I have updated the config schema (config-schema.json) — no new config options
  • I have added/updated tests to cover my changes

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 84.86352% with 61 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/virtual_members/laravel/validated_shape.rs 85.28% 34 Missing ⚠️
src/type_engine/call_resolution/return_types.rs 51.51% 16 Missing ⚠️
src/virtual_members/laravel/validation_rules.rs 91.07% 5 Missing ⚠️
src/analyse/run.rs 0.00% 2 Missing ⚠️
src/type_engine/call_resolution/target_cache.rs 92.30% 2 Missing ⚠️
src/type_engine/variable/rhs_resolution/calls.rs 95.34% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@shuvroroy shuvroroy changed the title L38 — Typed validated() array shapes from rules* L38 — Typed validated() array shapes from rules Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants