Download Latest Version 2.2.16 source code.zip (12.3 MB) Google Add to Preferred Sources
Home / 2.2.15
Name Modified Size InfoDownloads / Week
Parent folder
phpstan.phar 2026-09-23 30.0 MB
phpstan.phar.asc 2026-09-23 833 Bytes
2.2.15 source code.tar.gz 2026-09-23 12.3 MB
2.2.15 source code.zip 2026-09-23 12.3 MB
README.md 2026-09-23 10.4 kB
Totals: 5 Items   54.6 MB 6

Bleeding edge 🔪

  • Report non-stringable names in variable variables, dynamic method calls and dynamic static property/method access (#5871), [#4710], thanks @VincentLanglet and @staabm!

If you want to see the shape of things to come and adopt bleeding edge features early, you can include this config file in your project's phpstan.neon:

includes:

    - vendor/phpstan/phpstan/conf/bleedingEdge.neon

Of course, there are no backwards compatibility guarantees when you include this file. The behaviour and reported errors can change in minor versions with this file included. Learn more

Improvements 🔧

  • PHPStan supports running on PHP 8.6 runtime
  • php-8-stubs were updated with new and changed functions too
  • Full analyser support for new PHP 8.6 features is coming later this year
  • Remove the PHP version constraint from the #[\NoDiscard] attribute rules. (#6444), [#14586], thanks @claudepache!
  • Support for different versions of native PHP extensions, for example ext-ds v1 vs. v2 (#6250), [#14539], thanks @simPod!
  • only ext-ds and ext-couchbase are currently supported
  • PHPStan uses the extension version constraint from composer.json
  • Check for property hooks being pure/impure (#6246), thanks @AJenbo!
  • Add Error class to uncheckedExceptionClasses by default (https://github.com/phpstan/phpstan-src/commit/2fd897a5a9d0a639ea74cd77c63ea8fe7d2c6e92), [#15271]
  • Resolve conditional @throws types like ($x is 0 ? Exception : void) at call sites and throw points (#5874), [#7906], [#9497], thanks @VincentLanglet and @staabm!
  • Update nikic/PHP-Parser to 5.9.0 (#6498)
  • Detect FILTER_THROW_ON_FAILURE in filter_input(), filter_var_array() and filter_input_array() (#6514)
  • Report function calls with an argument count no variant accepts (#6531)

Bugfixes 🐛

  • Keep an optional path as written where a plain one would be (#6452), [#15238], thanks @SanderMuller!
  • Wrap NameResolver errors into ParserErrorsException so they are attributed to the file they come from (#6455), [#15252]
  • Write the offset instead of intersecting with HasOffsetValueType when overwriting an ArrayDimFetch (#6456), [#15246]
  • Merge sub-expression throw points, impure points, hasYield and terminating flags instead of overwriting them (#6457), [#15249]
  • Derive the % result range from the divisor's magnitude and the dividend's sign and bounds (#6458), [#15243]
  • ParametersAcceptorSelector: keep the acceptor-level variadic flag separate from the per-parameter one (#6460), [#15251]
  • Stop tracking the next implicit array key once it reaches PHP_INT_MAX (#6461), [#15244]
  • Do not use PHPDoc types as native types in foreach shape unrolling, list destructuring and by-ref writeback (#6463), [#15250]
  • Detect trait and parent class reference cycles instead of walking them forever (#6465), [#8082]
  • Pass the dim fetch paired with the offset to shouldKeepList() and guard the tracked-link setExistingOffsetValueType() shortcut (#6466), [#15245], thanks @staabm!
  • Compare literal array offsets as the keys they become (#6466), [#15245], thanks @staabm!
  • Detect overflowing << bounds, keep float for PHP_INT_MIN / -1, and bound % on non-integer operands (#6459), [#15242]
  • Track implicit indices past unpacked constant arrays and do not append past PHP_INT_MAX (#6464), [#15247], [#15248]
  • Advance the implicit index by an unpacked item's integer keys in array literals (#6462), [#15247]
  • Mark throw points coming from a throw expression and keep them as an effect of an expression statement (#6471), [#15258]
  • Narrow conditional type branches through NarrowedSubjectType instead of by identity (#6480), [#15268]
  • Do not step past PHP_INT_MAX when listing an integer range's finite types (#6481)
  • Memoize the expression keys of global constant lookups (#6481)
  • Normalize array keys through toArrayKey() in array_fill_keys and array_combine return types (#6078), [#14980], thanks @VincentLanglet and @staabm!
  • Invalidate maybe-impure function return values after impure method/static calls (#5667), [#13416], [#12734], thanks @VincentLanglet and @staabm!
  • Constant-fold explode() into a ConstantArrayType when separator, string and limit are all constant (#6123), [#15013], thanks @VincentLanglet and @staabm!
  • Un-prefix Filter\ and PDO\ class name strings in the PHAR (#6512), [#15007]
  • Infer rand() with $min greater than $max as the swapped range (#6531)
  • Do not infer false for get_class() without arguments on PHP 8 (#6531)
  • Do not let placeholder methods of intersection members override declared methods, properties, constants (#6537)

Performance 🏎️

  • Resolve a node's file and package dependencies in one pass over unique reflections (#6475)
  • Answer per node class what resolveDependencies() can reach (#6478), thanks @SanderMuller!
  • Skip rewriting an unchanged result cache (#6432), thanks @zonuexe!
  • Do not call range() for ranges longer than ARRAY_COUNT_LIMIT (#6531)

Function signature fixes 🤖

  • Add ReflectionClassConstant constructor throw type extension (#6440)
  • Fix the type of the options of the RedisArray constructor (#6399), thanks @mlocati!
  • Add the PHP 8.5 trace key to error_get_last() (#6470), thanks @janedbal!
  • Describe Random\Randomizer array, bytes and integer methods with dedicated dynamic return type extensions (#6469), [#15256], thanks @VincentLanglet and @staabm!
  • Correct GearmanClient unique parameters (#6241), thanks @donatj!
  • Allow FILTER_THROW_ON_FAILURE in $options of filter_var() and filter_input() (#6513), [#15007]
  • Because recent jetbrains/phpstorm-stubs update added @throws ...Error for a lot of core functions, we had to introduce a lot of throw type extensions to negate the effect on analysis. The analysis recognizes cases from the AST and types when the Error can never be thrown.
  • Add min() and max() throw type extension (#6516)
  • Add printf family throw type extension (#6517)
  • Add round() throw type extension (#6520)
  • Add str_split() throw type extension (#6522)
  • Add array_chunk() throw type extension (#6524)
  • Add get_class() throw type extension (#6525)
  • Add unserialize() throw type extension (#6528)
  • Accept all eight rounding modes of round() on PHP 8.4 (#6531)
  • DynamicFunctionReturnTypeExtensions for PostgreSQL (#6074), thanks @vrana!

Internals 🔍

  • Add setShouldNotImplyOppositeCase() on SpecifiedTypes to replace FAUX function call workarounds (#5769), [#14705], thanks @VincentLanglet and @staabm!
  • Improve TypeCombinator::addNull (#6493), thanks @VincentLanglet!
  • Keep never in MutatingScope::intersectButNotNever() instead of widening it to null (#6507)
  • Do not create a throw point for void returned by dynamic throw type extensions (#6515)
  • Replace PrintfHelper with PrintfFormatParser (#6517)
  • RequiredPhpVersionCommentTest cover PHPStan/Build/data (#6534), thanks @staabm!
  • Stop building Linux ZTS turbo binaries (https://github.com/phpstan/phpstan-src/commit/a62e61a23b5855a6cdfde1126ddf0ed8946270ac)
Source: README.md, updated 2026-09-23