Download Latest Version 2.2.2 source code.tar.gz (4.0 MB)
Email in envelope

Get an email when there's a new version of PHPStan

Home / 2.1.56
Name Modified Size InfoDownloads / Week
Parent folder
phpstan.phar 2026-05-26 26.8 MB
phpstan.phar.asc 2026-05-26 833 Bytes
2.1.56 source code.tar.gz 2026-05-26 4.0 MB
2.1.56 source code.zip 2026-05-26 4.0 MB
README.md 2026-05-26 6.8 kB
Totals: 5 Items   34.8 MB 0

This is the final send-off for PHPStan 2.1.x series! 👋 This release fixes 31 issues 🎉

PHPStan 2.2.0 will be released this Thursday.

Bleeding edge 🔪

  • Add unused-label rule on level 4 (#5701), [#11406]

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 🔧

  • Simulate loop analysis for goto-label pairs (#5701), [#14641], [#920], [#14638], [#4674], [#7711], [#7734], [#9904], [#11731], [#12167]
  • Add non-ignorable goto-to-undefined-label rule on level 0 (#5701)
  • Configuration defined type validation: Improve error message (#5700), thanks @staabm!
  • Report abstract method overriding non-abstract method in OverridingMethodRule and OverridingPropertyRule (#5730), [#14457]

Bugfixes 🐛

  • Preserve TemplateType in ArrayType and IntersectionType array-mutating methods (#5698), [#14633], thanks @staabm and @VincentLanglet!
  • Do not treat method_exists() as always true for @method-annotated methods (#5664), [#6211], thanks @VincentLanglet and @staabm!
  • Add implicit throw point for dynamic instantiation of non-final classes without constructors (#5683), [#6574], thanks @VincentLanglet and @staabm!
  • Do not let conditional expression undo explicit type narrowing (#5710), [#14645]
  • Narrow types after strlen() (#5703), [#13688], thanks @staabm and @VincentLanglet!
  • Do not use callable parameter types as native types for closure and arrow function parameters (#5632), [#11014], [#5271], thanks @VincentLanglet and @staabm!
  • Handle goto and Label in top-level file statements processed by processNodes (#5721), [#14660]
  • Suppress undefined static property error when property_exists() guard is present (#5544), [#2861], thanks @VincentLanglet and @staabm!
  • Do not create conditional expression when holder and guard have the same type and guard overlaps with other branch (#5724), [#14469], thanks @VincentLanglet!
  • Retain class_exists expression types in closure (#5746), thanks @staabm!
  • Do not report function_exists as always-true conditions (#5739), [#8980], thanks @staabm!
  • Code around enum_exists() does not complain about nonexistent classes (#5751), thanks @staabm!
  • Check all interfaces instead of only immediate ones for constructor enforcement in NewStaticRule (#5740), [#10274], thanks @VincentLanglet and @staabm!
  • Process reordered named arguments in call-site order in processArgs (#5725), [#9392], thanks @VincentLanglet and @staabm!
  • Project IssetExpr certainty narrowing through ternary-assigned variables via conditional expressions (#5742), [#10090], thanks @VincentLanglet and @staabm!
  • Use similar behavior for always returning never method and sometimes ones (#5747), [#7799], thanks @VincentLanglet!
  • Only suppress implicit throw point for Throwable-returning calls inside throw expressions (#5741), [#9826], thanks @VincentLanglet and @staabm!
  • Recognize promoted property variable usage in constructor body as property usage (https://github.com/phpstan/phpstan-src/commit/1b1b65c799495592b6d76a603ad4456493eb5788), [#14703]

Performance 🏎️

  • Bail to MixedType in deep dim fetch writes on oversized arrays (#5681), [#14624], thanks @staabm and @VincentLanglet!
  • Prevent nested foreach unrolling to fix exponential blowup (#5732), [#14674], thanks @staabm!

Function signature fixes 🤖

Internals 🔍

  • Reflection Golden Tests: Report changes via GitHub Actions annotation (#5697), thanks @staabm!
  • Move list-contradiction NeverType out of unsetOffset into tryRemove (#5707)
  • Extract Type::truncateListToSize() from TypeSpecifier (#5713)
  • Improve variable name (#5736), thanks @staabm!
  • Cleanup ClassExistsFunctionTypeSpecifyingExtension (#5748), thanks @staabm!
  • Test array_key_exists() on subtracted enum (#5749), thanks @staabm!
  • Added regression test (#5750), thanks @staabm!
  • Cleanup instanceof ConstantStringType calls (#5752, #5753), thanks @staabm!
Source: README.md, updated 2026-05-26