re #96 burn down PHPStan level-6 baseline (72 -> 11)#111
Merged
Conversation
added 2 commits
May 28, 2026 08:49
Fix 69 of the 80 grandfathered level-6 findings at root cause across ~25 files in 12 packages (no @PHPStan-Ignore, no widening, no baseline tricks). Parallel sub-agents handled the independent packages (Http, Validation, Security, Session, Sanitation, Courier, Doctor, Events, Happen, Introspection, Scaffold); the coupled/design-heavy slice (Cache, Common, Container, Structure) was done directly. Full test suite green (only the pre-existing ext-mongodb-absent MongoSessionHandlerTest errors remain). Highlights: - Real bugs fixed: HttpStatusCollection int/string confusion; the Windows path-length guard in FilesystemCacheItemStorage ('\\' === '/' was always false); Predis cluster classes moved to Predis\Connection\Cluster\* in predis 2.x; CreditCard/Ip/Isbn arithmetic on strings; Session gc() return types (void/true -> int|false); the unused validateToken expiry gap. - Type precision: Executable narrowed to ReflectionFunction|ReflectionMethod; Arr::getValue typed mixed (it genuinely handles array|object|other); Courier middleware array shapes; Sanitizer/Validator $payload -> interface. - Dead code removed: redundant is_array/is_string/method_exists guards, always-false branches, redundant array_values, unnecessary nullsafe. - SequenceTrait declares adjustCapacity() abstract instead of guarding with method_exists; PriorityNode priority/stamp are native int. Remaining 11 are decision-gated (tracked for follow-up): 8 trait.unused (public-API mixins exercised only by tests), 2 Cookie collection generics (divergent-contract LSP), 1 Cycle getRepository template (third-party loose-union generic).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Continues #96 toward an empty baseline. Fixes 69 of the 80 grandfathered level-6 findings at root cause — no
@phpstan-ignore, no type-widening-to-silence, no baseline tricks.phpstan-baseline.neonshrinks 72 → 11 entries.Work was parallelized: sub-agents fixed the independent packages (Http, Validation, Security, Session, Sanitation, Courier, Doctor, Events, Happen, Introspection, Scaffold); the coupled/design-heavy slice (Cache, Common, Container, Structure) was done directly. Every change verified centrally.
Notable real bugs fixed (not just annotations)
substron an int, impossibleinstanceof, unreachable code).'\\' === '/'— always false, so it never fired. NowDIRECTORY_SEPARATOR === '\\'.Predis\Connection\Cluster\*in predis 2.x (code imported the removedAggregate\*); also removed dead0 >= $lifespanbranches.gc()returnedvoid/trueinstead ofint|false.ReflectionFunction|ReflectionMethod(only concrete subtypes), fixinginvokeArgs()/invokeClosure().mixed(it genuinely handles array|object|other and recurses on mixed) — also fixes a latent nested-access TypeError.Dead code / precision
Redundant
is_array/is_string/method_existsguards, always-false branches, redundantarray_values, unnecessary nullsafe removed.SequenceTrait::adjustCapacity()is nowabstractinstead ofmethod_exists-guarded;PriorityNodeuses nativeint+ constructor promotion.Remaining 11 (decision-gated, follow-up)
trait.unused— public-API mixins (Data entity traits, etc.) exercised only by test fixtures, which PHPStan doesn't analyze (addingtests/to paths surfaces 1006 test-code findings — out of scope).CookieCollection/SetCookieCollectiondiverge fromMap<string, Cookie>(values()returns string cookie values), so no@extendsbinding is LSP-valid without a compose-vs-extend refactor.getRepositorytemplate — third-partyclass-string<T>|non-empty-string|Tunion prevents template inference; result is pinned via@var.Test plan
composer cs— cleancomposer stan(PHPStan 2.1, baseline 11) —[OK] No errorsvendor/bin/rector process --dry-run(full) — cleancomposer test— 5555 tests; only pre-existing localMongoSessionHandlerTestenv errors (CI loads ext-mongodb)