Repository navigation
2.1.41
Just three weeks after PHPStan 2.1.40, this release fixes whopping 87 issues! 🎉
Major new features 🚀
- Main documentation page on phpstan.org is now a dashboard linking the most common problem-solving pages
- All error identifiers reported by PHPStan now have comprehensive documentation.
- Each page shows a code example reporting the error
- Followed by an explanation why is it reported
- And showing one or more ways how to fix it
- Several awesome examples:
ternary.resultUnused,property.onlyRead,return.void
- Documentation about custom extensions now documents all previously-undocumented extension types
Improvements 🔧
- Add option
reportIgnoresWithoutCommentsto report ignores without comments (#5032), #11340, thanks @calebdw!- This disables
@phpstan-ignorewithout comments in parentheses - It also disables
@phpstan-ignore-lineand@phpstan-ignore-next-linecompletely - See: https://phpstan.org/config-reference#reportignoreswithoutcomments
- This disables
- Tuned how many CPU cores PHPStan uses by default:
- Diminishing returns beyond 8 CPU cores (phpstan/phpstan-src@23928d9)
- Different method to compute CPU cores to use (phpstan/phpstan-src@89f1382), #11410, #7479
- See docs: https://phpstan.org/config-reference#parallel-processing
- Solve various HTTP proxy and custom root CA errors when downloading PHPStan Pro
- Use plain old Guzzle and system CA (phpstan/phpstan-src@a3af1cd), #12486, #11244
- Report invalid printf placeholder (#4478), #1889, #8547, thanks @VincentLanglet!
- Respect rule level in ParameterCastableToNumberRule (#4873), thanks @VincentLanglet!
- Report non existent offset on non empty array (#4399), #7143, thanks @VincentLanglet!
- TableErrorFormatter - always show identifier, even if non-ignorable (phpstan/phpstan-src@d64ce37)
- Show instructions to coding agent about how to handle errors (phpstan/phpstan-src@bb42c9f)
- Tip about adding
@phpstan-impurewhere applicable (#5031), #14183 - Report error when trying to instantiate a trait with new (#5182)
Bugfixes 🐛
- Fix createConditionalExpressions (phpstan/phpstan-src@3993c52), #14191
- Differentiate signaturePrototype and inheritancePrototype (#4945), #11067, #12830, #12272, thanks @VincentLanglet!
- Avoid false error on is_subclass_of (#4472), #13713, thanks @VincentLanglet!
- Fix execution branch confusion (#5058), #5051, #9647, thanks @staabm and @VincentLanglet!
- Fix spurious error in specific combination of namespace blocks and function declaration with phpdoc type annotation (#5077), #13831, thanks @VincentLanglet!
- Fix SimplXmlElement and GMP casts (#5020), #14136, thanks @VincentLanglet!
- Fix: False match.unhandled on array with multiple booleans (#5107), #13029, thanks @VincentLanglet and @staabm!
- Fix seemingly same type reports as invalid/incompatible. (#5094), #13440, #12688, thanks @VincentLanglet!
- Fix:
$this(Type~Subtracted)does not work on conditional return type asType~Subtracted(#5104), #12244, thanks @staabm and @VincentLanglet! - Fix: False positive with array_key_exists and union types (#5114), #13526, thanks @staabm!
- Fix: Nonexistent offset detection on lists
if ($index < count($array))(#5090), #13770, thanks @VincentLanglet and @staabm! - Fix: Defining Array Constants in PHP Traits Causes Errors When Using Class Constants as Keys or Values (#5115), #11351, #11088, thanks @VincentLanglet!
- Fix: Generator suspension points should be treated as infinite loop break points (#5057), #6189, #10054, thanks @VincentLanglet and @staabm!
- Fix: BenevolentUnionType with generics produce confusing errors (#5070), #9732, thanks @staabm and @VincentLanglet!
- Fix while-true-if-break: Variable might not be defined (#5118), #11545, #10245, #11984, #5477, #5919, #9023, thanks @VincentLanglet!
- Fix: False positive staticMethod.impossibleType (#5121), #13566, #10337, thanks @staabm and @VincentLanglet!
- Fix: Variable $ in empty() always exists and is not falsy. (#5124), #14223, thanks @VincentLanglet and @staabm!
- Fix: Incorrect 'Variable $value might not be defined.' (#5125), #14117, #8430, #10657, thanks @VincentLanglet and @staabm!
- Fix: Assignment inside match statement no longer recognized (#5120), #13981, thanks @staabm!
- Fix: Incorrect: Class referenced with incorrect case, (#5064), #14205, thanks @staabm and @VincentLanglet!
- Fix offset might not exist false-positives (#5137), #14234, #14215, thanks @VincentLanglet!
- Consider ArrayAccess side effects for dead catch analysis (#5117), #11427, thanks @VincentLanglet!
- Fix: false positive on
in_array(...)check with impure second argument (#5141), #13799, thanks @VincentLanglet and @staabm! - Fix: Spreading an associative array into a generic function/method call may restrict optional arguments to their default values. (#5079), #12363, #8257, #7369, thanks @VincentLanglet and @staabm!
- Fix:
array_spliceresets int keys of the input array (#5139), #14037, thanks @staabm and @VincentLanglet! - Fix:
iterableis equal toarray|Traversable(#5144), #13247, thanks @staabm and @VincentLanglet! - Fix: Reassignment of $this is not an error (#5146), #3585, thanks @staabm!
- Fix spurious error nullCoalesce.offset (#5145), #13921, thanks @staabm!
- Support
chop()function as an alias ofrtrim()(#5157), thanks @zonuexe! - Fix: Assignment in a key of array destructuring is ignored (#5164), #14019, thanks @staabm and @VincentLanglet!
- Support sizeof() alias in addition to count() (#5179), thanks @staabm!
- TableErrorFormatter: Limit number of errors (#5136), thanks @staabm!
- Fix: list lost after overwriting last element (#5169), #14245, thanks @VincentLanglet and @staabm!
- Improve intersection of ConstantArray and AccessoryIsList (#5067), thanks @VincentLanglet!
- Fix list description with offset required (#5212), thanks @VincentLanglet!
- Fix: crash on first class callable as conditional do while (#5194), #12246, thanks @staabm and @VincentLanglet!
- Fix maybe-undefined variable regression in loops with unrelated assignments (#5208), #14269, #4284
- Fix regression: regex matches after checking non-empty array (#5209), #14270, #12397, thanks @staabm!
- Propagate
@phpstan-assert-*annotations to First-class callables (Closures) and string callables (#5201), #14249, thanks @staabm! - Fix: non-negative-int evaluated to int (#5176), #12163, thanks @staabm and @VincentLanglet!
- Fix: Error „should return static(Test) but returns Test“ (#5190), #4860, thanks @VincentLanglet!
- Fix: PHPDoc types from overridden function are not included in trait typeinfo when aliased (#5204), #9733, thanks @VincentLanglet!
- Fix: Index for loop inference should only work in lists (#5215), #13773, thanks @VincentLanglet!
- Fix: Return in finally does not always overwrite return in try-catch (#5163), #6670, #12215, #11906, #7665 thanks @VincentLanglet and @staabm!
- Fix: "Variable might not be defined" false positive (#5216), #14274, thanks @staabm!
- Fix: should return
array{a: string, b: int, c: int}but returnsnon-empty-array<'a'|'b'|'c', int|string>(#5193), #12665, #14080, #8774, #9907, #11006, thanks @VincentLanglet! - Avoid duplicated InternalThrowPoint when simulating ArrayAccess calls (#5222), thanks @VincentLanglet!
- Fix: type narrowing on non-empty-list array shape (#5227), #14297
- Fix: false positive “Match expression does not handle remaining value: int<...>” for
match (count(...)) { ...}(#5228), #12790 - Fix count()-based type narrowing on unions of constant array shapes (#5229), #14301, #11488
Function signature fixes 🤖
- Update PDOStatement stub (#5132), #14206, #9120, thanks @VincentLanglet!
- Add get_headers stub (#5140), #13835, thanks @VincentLanglet!
Performance 🏎️
- Faster MutatingScope->getNodeKey() (#5014), thanks @staabm!
- Faster IsSuperTypeOfResult creation (#5042), thanks @staabm!
- Faster LazyInternalScopeFactory->create() (#5043), thanks @staabm!
- Faster TrinaryLogic::maxMin(), TrinaryLogic::lazyMaxMin() (#5045), thanks @staabm!
- Prevent
TypeCombinator::intersect()calls inMutatingScope-> specifyExpressionType()(#5048), thanks @staabm! - Prevent unnecessary
$scope->getType()calls (#5051), thanks @staabm! - Prevent unnecessary work in
UnionType->describe()(#5062), thanks @staabm! - Fix slow analysis on return with large OR condition chains (#5076), #14207
- Fix slow analysis on large AND condition chains (phpstan/phpstan-src@5b6cb3a), #14214
- Prevent unnecessary work in IntersectionType (#5054), thanks @staabm!
- AcceptsResult: cache Yes/No/Maybe (#5095), thanks @VincentLanglet!
- TemplateTypeTrait: Prevent unnecessary work (#5122), thanks @staabm!
- MutatingScope->createConditionalExpressions(): cheap checks first (#5126), thanks @staabm!
- MemoizingContainer - memoize getServicesByTag (phpstan/phpstan-src@6a7d9e0)
Internals 🔍
- Add AnalysisResult::withFileSpecificErrors() to public API (#5034), thanks @janedbal!
- Add non regression test (#5035), thanks @VincentLanglet!
- Lint workflows (#5041)
- Added regression tests (#5050), #10559, #11534, thanks @staabm!
- Regression tests (#5076)
- Added regression test (#5088), thanks @staabm!
- Add non regression tests (#5110), thanks @VincentLanglet!
- Add non regression test (#5109), thanks @VincentLanglet!
- TypeSpecifier refactor (#5123), thanks @staabm!
- Fix 'restricted open_basedir' e2e test (#5138), thanks @staabm!
- Rework LegacyNodeScopeResolverTest (phpstan/phpstan-src@b0019e9)
- Slim down LegacyNodeScopeResolverTest (phpstan/phpstan-src@7b5e618)
- More slimming down (phpstan/phpstan-src@bd783aa)
- Slim down tests that used
replaceClass=true(phpstan/phpstan-src@27d2abd) - Final LegacyNodeScopeResolverTest cleanup (phpstan/phpstan-src@456275f)
- Refactor: NonNullabilityHelper (#5154), thanks @staabm!
- Simplify NonNullabilityHelper (#5158), thanks @staabm!
- Fix typo (#5180), thanks @staabm!
- Trivial code style fixes (#5159), thanks @zonuexe!
- Start using phpbench (phpstan/phpstan-src#5200)
- Added missing namespace to test (#5214), thanks @staabm!
- Remove default handling of truthy/falsey callback because it's not applicable in these expressions (phpstan/phpstan-src@be0124d)
- Some handlers only need to reference truthy/falsey scope of the processed expression (phpstan/phpstan-src@bee17d3)