🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Releases: phpstan/phpstan

2.2.8

Choose a tag to compare

@phpstan-bot phpstan-bot released this 04 Aug 22:23
Immutable release. Only release title and notes can be modified.
e285254

Bugfixes 🐛

  • Narrow the right side of ??= with falsey isset() instead of !== null (#6145), #15021, thanks @VincentLanglet and @staabm!
  • ArrayType::isCallable(): ask StringType::isSuperTypeOf() about the item type instead of only isString() (#6166), #13114
  • Conjoin alternative-form entries in SpecifiedTypes::unionWith() instead of keeping only the left one (#6173), #15039
  • Do not narrow the falsey branch of a nested isset() at its intermediate offset (#6175), #15005, thanks @SanderMuller!
  • Store PhpStorm stub paths in the reflection cache relative to the stubs root (#6179), #15023
  • Turbo extension: Resolve comment token ids at runtime in the native parser (#6180), #15037, #15043
  • Rebuild GatheringNodeCallback layers in VirtualAssignNodeCallback instead of wrapping them (#6172), #15038

Performance 🏎️

  • Faster handling of enums with lots of cases (#6160), thanks @staabm!
  • Memoize the isGenerator() yield scan on the AST node (#6161)
  • Answer UnionType comparisons from an identity-keyed FiniteTypeSet instead of scanning every member (#6116), #15008, #14978, thanks @staabm and @SanderMuller!

Function signature fixes 🤖

  • Make ReflectionObject, RecursiveFilterIterator, ParentIterator, RecursiveCachingIterator and RecursiveRegexIterator generic in stubs (#6165), #15032

Internals 🔍

  • Resolve isset/empty/?? chains from handler-built descriptors (#6144)
  • Split processAssignVar into prepareTarget and applyWrite, compose the ??= read (#6144)
  • Walk the dynamic variable name once, drop the vestigial clone walks (#6144)
  • Add parameter closure type extensions for array_map, array_filter, array_walk, array_find (#6147)
  • Resolve the native flavour of closure parameters through parameter closure type extensions (#6147)
  • Derive ArrayAccess and __set simulation throw points directly instead of walking synthetic calls (#6148)
  • Extract the intrinsic closure-parameter blocks into ParametersAcceptorSelector::applyIntrinsicArgOverrides() (#6149)
  • Derive expression-statement exit points from the never type (#6150)
  • Reference the original chain in ExistingArrayDimFetch, delete DeepNodeCloner (#6151)
  • Let the compositional-key shortcut clear virtual-node keys on the invalidated side (#6154)
  • Do not extend Expr in the isset/empty/coalesce rule-facing virtual nodes (#6155)
  • Add ShellExecHandler and IssetExprHandler (#6156)
  • Run the impossible-check and nullsafe rules on post-processing virtual nodes (#6157)
  • Process call arguments in a single pass with type-driven acceptor selection (#6158)
  • Improve #[InstanceofDeprecated] message of EnumCaseObjectType (#6159), thanks @staabm!
  • Check yield operand voidness through getKeepVoidType() (#6161)
  • Drop redundant @internal on hasAcceptorTemplateOrLateResolvableParameterType (#6161)
  • Pass the iteratee type into enterForeach() and enterForeachKey() (#6162)
  • Resolve intertwined by-ref slot types from the just-assigned root type (#6162)
  • Filter FiberScope state in the falsey direction and carry both filter lists (#6164)
  • Check destructured @var items against the native offset type (#6164)
  • Defer match arm comparison errors only for match(true)-style subjects (#6164)
  • Scope deferred constant-condition errors and markers per file (#6164)
  • Add deferred SpecifiedTypes machinery evaluated at the application point (#6163), #14908, #14966
  • Defer boolean-decomposition holder math to the application point (#6163)
  • Add regression test for #14908 (#6163)
  • Do not derive holder antecedents from truthy narrowing weaker than the truth (#6163)
  • Specify expression types in place on an unpublished working copy (#6168)
  • Use a complete version constraint in FiniteTypeSetTest's RequiresPhp attribute (#6177), thanks @SanderMuller!
  • Harden the turbo-token-numbering job against zizmor findings (#6180), #15037, #15043
  • Harden phar.yml per zizmor across all jobs (#6180), #15037, #15043

2.2.7

Choose a tag to compare

@phpstan-bot phpstan-bot released this 29 Jul 17:40
Immutable release. Only release title and notes can be modified.
692db47

Bugfixes 🐛

  • Preserve maybe-certainty only for Variable when narrowing the base of ?->, ??, isset() and empty() (#6109), #15002, thanks @staabm and @VincentLanglet!
  • Do not key the container cache on the turbo extension state (#6121)
  • Fill the missing gaps in expr processing (phpstan/phpstan-src@eea2788)
  • Resolve a relative include against the trait file in a trait context (#6127), thanks @zonuexe!
  • Do not let type narrowing define a certainly-undefined variable (#6130), #2032
  • Merge all callable acceptors' parameters into NativeParameterReflection when a closure is passed to a union of callables (#6128), #15003, thanks @staabm and @VincentLanglet!
  • Treat a property with a default value as always set in isset resolution (#6131), #10786
  • Read already-processed expression types from ExpressionResults in NodeScopeResolver (#6139), #13253
  • Resolve __DIR__ and __FILE__ against the trait file in a trait context (#6126), #15015, thanks @zonuexe!

Performance 🏎️

  • Reuse the scope factory of the other flavour (#6114)
  • Remember chain levels that shortcircuit to themselves (phpstan/phpstan-src@ab11f34), #14991
  • Prevent unnecessary re-creation of union types (#6117), thanks @staabm!
  • Remember an expression's printed form as the printer produces it (#6118), #14991
  • Prevent unnecessary re-creation of benevolent union types (#6119), thanks @staabm!
  • Resume expression-asking fibers with ExpressionResults (phpstan/phpstan-src@9725942)
  • Create merge conditionals from the differing holders only (#6141)

Internals 🔍

  • ExprHandlerRegistry does not need to be AutowiredService (phpstan/phpstan-src@36392ba)
  • Repeat a shadowed class's interfaces on its stub shell (#6113)
  • Run the benchmark on PHP 7.4 in addition to PHP 8.5 (#6121)
  • Check bench/data files with RequiredPhpVersionCommentTest (#6122), thanks @staabm!
  • Introduce ExpressionResultFactory (phpstan/phpstan-src@8f5111f)
  • ExpressionResult - add beforeScope (phpstan/phpstan-src@a7094b5)
  • ExpressionResult - add Expr (phpstan/phpstan-src@abcce56)
  • Eliminate the OriginalPropertyTypeExpr virtual node (#6129)
  • Eliminate the GetOffsetValueTypeExpr virtual node (#6129)
  • Eliminate the GetIterableKeyTypeExpr virtual node (#6129)
  • Eliminate the GetIterableValueTypeExpr virtual node (#6129)
  • Deduplicate constant-condition vs impossible-check reports via collectors instead of asking the type specifier inline (#6132)
  • Replace SpecifiedTypes::normalize() with symbolic alternative-form entries (#6133)
  • Resolve early-terminating calls to an explicit never type in the call handlers (#6134)
  • Read operand types from ExpressionResults in Throw/BooleanAnd/Coalesce handlers (#6135)
  • Read operand types from ExpressionResults in Ternary/ArrayDimFetch/PropertyFetch handlers (#6136)
  • Read operand types from ExpressionResults in BinaryOp/BooleanOr/MethodCall/Match handlers (#6137)
  • Read expression types from ExpressionResults in NodeScopeResolver and handlers (#6138)
  • Fill the foreach key-loop native types with the native flavour (#6141)
  • Run engine-feeding node-callback gatherers synchronously at the emission position (#6142)
  • Track containsNullsafe on ExpressionResult and propagate it through fetch/call chains (#6143)

1.12.34

Choose a tag to compare

@phpstan-bot phpstan-bot released this 28 Jul 10:05
Immutable release. Only release title and notes can be modified.
4dd89ca

2.2.6

Choose a tag to compare

@phpstan-bot phpstan-bot released this 26 Jul 21:24
Immutable release. Only release title and notes can be modified.
a6e9b5a

This release fixes 33 issues! 🎉

PHPStan Turbo

Major new features 🚀

  • PHPStan Turbo (https://github.com/phpstan/turbo-ext/)
    • Optional native PHP extension (PHP 8.3+) written in C++ that makes running PHPStan 10-30 % faster (depending on project specifics)
    • Users installing PHPStan through Composer with phpstan/phpstan get it automatically. Composer package ships prebuilt binaries for the most common platforms — Linux (glibc and musl, x86_64 and arm64), macOS, and Windows (x86_64)
    • Users running standalone phpstan.phar can install the extension with pie install phpstan/turbo
    • The fact that it's enabled can be verified with vendor/bin/phpstan diagnose or running analyse -vvv
    • There's room to improve performance with this technique in the future, but we're shipping it now because it brings real benefits already.

Bleeding edge 🔪

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 🔧

Bugfixes 🐛

Performance 🏎️

  • Cache ObjectType instead of re-creating it over and over (#6006), thanks @staabm!
  • Single-flight cold directory scans in OptimizedDirectorySourceLocatorFactory (#5846), thanks @SanderMuller!
  • Disable zend.assertions as suggested by PHP-Parser (#6021), thanks @staabm!
  • Faster DuplicateClassDeclarationRule (#6038), thanks @staabm!
  • Faster DuplicateFunctionDeclarationRule (#6039), thanks @staabm!
  • Memoize ExprHandler dispatch in MutatingScope::resolveType() (#6040), thanks @staabm!
  • Replace NodeFinder with direct recursion in shouldInvalidateExpression() (#6041), thanks @staabm!
  • Return early from ClassReflection::getMethod() cache (#6043), thanks @staabm!
  • Index PSR autoloader locators by symbol instead of sweeping them per lookup (#6037)
  • Short-circuit no-op remove() comparisons by identity before equals() (#6037)
  • Cache reflections built from the PhpStorm stubs (phpstan/phpstan-src@ae5fd31)
  • Do not park fibers on expressions that can never receive a before-scope (#6064)
  • Extend the compositional-key shortcut to more invalidation scans (#6064)
  • Prevent unnecessary method calls on Type (#6076), thanks @staabm!
  • Prevent reflection when Property Hooks not supported (#6082), thanks @staabm!
  • Iterate through nullsafe expression chains (#6084), thanks @realFlowControl!
  • Iterate in collectInterfaces() (#6092), thanks @staabm!
  • Iterate in getBooleanExpressionDepth() (#6091), thanks @staabm!
  • Prevent duplicate filterByTruthyValue() work in NodeScopeResolver (#6103), thanks @staabm!
  • Run indentation detection, node cloning and node replaci...
Read more

2.2.5

Choose a tag to compare

@phpstan-bot phpstan-bot released this 05 Jul 06:33
Immutable release. Only release title and notes can be modified.
909c1e5

Improvements 🔧

Bugfixes 🐛

  • Allow null values in native preg_replace_callback callback array type for PREG_UNMATCHED_AS_NULL (#5987), #14904, thanks @staabm!

Performance 🏎️

  • Restore process-wide statics from the main container after stub validation (#5984)
  • Drop the container reference in LazyClassReflectionExtensionRegistryProvider after building the registry (#5985)
  • Replace PhpClassReflectionExtension::evictPrivateSymbols() with a shared LRU over the member caches (#5986)
  • Make the member cache LRU limit configurable as cache.memberCacheKeysMax (#5986)
  • LRU-cap resolved local type aliases in UsefulTypeAliasResolver (#5989)
  • Make the cap configurable via cache.resolvedLocalTypeAliasesCountMax (#5989)
  • Raise CachedParser source-byte cap to 4 MB, add eviction floor, make it configurable (phpstan/phpstan-src@354e926)
  • Give CachedParser $cachedSourceBytesMax a default value (phpstan/phpstan-src@fa1003a)
  • Flatten deep BooleanOr chains in resolveType() to avoid O(n^2) scope narrowing (#5992), #14477, thanks @SanderMuller!
  • Cache per-guard isSuperTypeOf() results in createConditionalExpressions() instead of recomputing them per target (#6001), #14920
  • Skip constant-array guards when creating conditional expressions for subtype-absorbed targets (#6002), #14921
  • Compute ConstantArrayType sealed-shape isSuperTypeOf() reasons lazily via IsSuperTypeOfResult closures (#6003), #14918
  • Memoize the ExprHandler lookup by Expr class in specifyTypesInCondition() and processExprNode() (#5999), #14919

Function signature fixes 🤖

Internals 🔍

2.2.4

Choose a tag to compare

@phpstan-bot phpstan-bot released this 03 Jul 07:01
Immutable release. Only release title and notes can be modified.
f0fe3fb

PHPStan addresses the RAMpocalypse! It now consumes a lot less memory. See for yourself by running analyse -v.

E.g. running PHPStan on itself went from 2.8 GB to 2.1 GB total consumed memory across worker processes.

Bugfixes 🐛

  • Skip boolean conditional holders whose target was dropped as a no-op antecedent narrowing (#5958), #14891, thanks @VincentLanglet!
  • Distrust a TemplateType member's eager Yes in IntersectionType::isAcceptedBy only when that member accepts with Yes (#5962), #14893, thanks @staabm!
  • Forget the tracked ob_get_level() after impure calls that may open or close output buffers (#5964), #14895, thanks @staabm and @VincentLanglet!

Performance 🏎️

  • PackageDependencyResolver: memoize resolvePackage per file (#5961), thanks @SanderMuller!
  • Evict parser and PHPDoc name-scope caches by LRU instead of FIFO (#5965)
  • Remove custom isSuperTypeOf reasons from ObjectType (#5968), #14896
  • Restore value sharing in name scope maps hydrated from the file cache (#5969)
  • Cap CachedParser by total cached source size (#5969)
  • Keep a single memoization layer for located reflections (#5974)
  • Stream the result cache to disk instead of building it in memory (phpstan/phpstan-src@ee9fe9e)

Internals 🔍

2.2.3

Choose a tag to compare

@phpstan-bot phpstan-bot released this 30 Jun 21:16
Immutable release. Only release title and notes can be modified.
4048833

This release fixes 52 issues! 🎉

Bleeding edge 🔪

  • Report new on an expression whose type is not string|object via new.nonObject (#5866), #4922, thanks @VincentLanglet and @staabm!
  • RequireFileExistsRule: Fix Differing behaviors when requiring or including relatively vs using __DIR__ (#5879), thanks @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 🔧

  • Result cache: Invalidate only package-dependent files when a Composer package changes (#5933), thanks @SanderMuller!
  • Prevent ENV var tokens from being leaked by commited DI containers (#5820), thanks @staabm!
  • Explain unresolvable and impossible types with reasons (#5827)
  • Support type predicates on callable and Closure types (#5837), #14800, #11139
  • Implement AccessoryDecimalIntegerStringType::tryRemove() and preserve accessories when re-unioning '0' (#5816), #14785, thanks @staabm and @VincentLanglet!
  • Enumerate constant strings from bounded regex quantifications (a?, a{n}, a{n,m}) (#5860), #14820, thanks @staabm!
  • Preserve variable certainty when narrowing the base of a nullsafe operator (#5870), #7291, thanks @VincentLanglet and @staabm!
  • Support ::class magic constant in array shape keys and const types (#5891), thanks @janedbal!
  • Infer non-falsy-string&non-decimal-int-string for the magic name property on the UnitEnum/BackedEnum interfaces (#5894), #14839, thanks @staabm and @VincentLanglet!
  • Narrow ob_get_contents()/ob_get_clean()/ob_get_flush()/ob_get_length() to non-false while output buffering is active (#5909), #10348, thanks @staabm and @VincentLanglet!
  • Support treatPhpDocTypesAsCertain for null-safe methods/properties (#5924), thanks @rvanvelzen!
  • Do not let a TemplateType member force Yes acceptance of an intersection (#5926), #13190, thanks @rvanvelzen!
  • Report always-true in_array(..., true) when every finite needle value is guaranteed in the haystack (#5944), #14873, thanks @staabm and @VincentLanglet!

Bugfixes 🐛

  • Narrow the match subject when its assigned result is later narrowed (#5808), #14772, #10843
  • Do not create never-narrowing conditional expression holders in BooleanAnd/BooleanOr decomposition (#5809), #14774
  • Gather all conjuncts of a compound condition side into BooleanAnd/BooleanOr conditional holders (#5810), #14780
  • Do not split a swapped negated-conjunction holder side into per-expression holders (#5810), #14780
  • Infer non-empty-list for preg_match_all() matches when the match succeeded (#5812), #14781, thanks @staabm and @VincentLanglet!
  • Do not split a compound-boolean holder side whose asserted truth value is a disjunction (#5817), #14787
  • Narrow regex subject to decimal-int-string when every alternation branch is a decimal integer (#5814), #14784, thanks @staabm!
  • Narrow ctype_digit() argument to numeric-string instead of decimal-int-string (#5822), #14792
  • Revert #5793 (#5825), thanks @staabm!
  • Preserve keyed array prefix as unsealed tail when adding a general array with + (#5832), #14799
  • Skip conditional expression guard when guard type is a subtype of the other branch's value (#5848), #14807
  • Narrow switch case branch from the case condition's plain scope instead of its truthy scope (#5852), #14814
  • Treat a regex alternation as maybe-empty when any branch is maybe-empty in isMaybeEmptyNode (#5851), #14809, thanks @staabm and @VincentLanglet!
  • Combine alternation branch literals with their preceding prefix in regex group types (#5851), #14809, thanks @staabm and @VincentLanglet!
  • Decompose union offset types in ConstantArrayType::flipArray() and fillKeysArray() to preserve per-key value precision (#5719), #14656, thanks @VincentLanglet and @staabm!
  • Report exceptions thrown from ResultCacheMetaExtension during result cache restore as internal errors (#5853), #14805, thanks @staabm and @VincentLanglet!
  • Include null in return type of Closure::bindTo() and Closure::bind() dynamic return type extensions (#5675), #5009, thanks @VincentLanglet and @staabm!
  • Treat decimal-int-string as a numeric string in looseCompare() instead of assuming inequality with non-decimal strings (#5824), #14793, thanks @VincentLanglet and @staabm!
  • Consider is_file($path) before checking require $path (#5867), thanks @staabm!
  • Use genuine falsey narrowing (not the inverted truthy narrowing) for the consequent of BooleanAnd false-context conditional holders (#5878), #14828
  • Narrow array element type after a keyless foreach whose body guards each element with an early exit (#5877), #5755
  • Remember call expression as truthy/falsey alongside @phpstan-assert-if-true argument narrowing (#5885), #14829, thanks @staabm!
  • Remember method/static call expression as truthy/falsey alongside @phpstan-assert-if-true argument narrowing (#5880), thanks @staabm and @VincentLanglet!
  • Keep subtype-absorbed variables as conditional-expression targets when merging branches (#5876), #7948, #4905, thanks @VincentLanglet and @staabm!
  • Enter right-side-assign context for ??= so closures capturing the assigned variable by reference see its assigned type (#5900), #13810, thanks @staabm!
  • Propagate hasYield from yield in ternary branches (#5904), #5681, thanks @staabm and @VincentLanglet!
  • Normalize constant-string member access ($obj->{'n'}) to bareword form when printing expression keys (#5916), #14847, thanks @staabm and @VincentLanglet!
  • Do not report invariant template type mismatch when both type arguments are the same template parameter narrowed by control flow (#5921), #13190, thanks @rvanvelzen!
  • Prevent "Unresolvable type" errors when mapping constant arrays (#5936), #14844, thanks @staabm and @VincentLanglet!
  • Preserve template bound for enum-case, integer-range and constant-bool subtypes in TemplateTypeFactory::create() (#5905), #10083, thanks @staabm and @VincentLanglet!
  • Re-add complement of a dropped self-condition to boolean-decomposition holder types (#5943), #14874, thanks @VincentLanglet and @staabm!
  • Skip degenerate no-op antecedents when building boolean conditional expression holders (#5951), #14878, thanks @VincentLanglet and @staabm!
  • Resolve class-string expressions to object types when detecting unused private methods, constants and static properties (#5953), #14880, thanks @staabm and @VincentLanglet!
  • Treat plain class-string as a definite subtype of class-string<object> in GenericClassStringType::isSuperTypeOf() (#5956), #14887
  • Invalidate outer-scope expressions mutated by closures, arrow functions and callables passed as arguments (#5957), #14888

Performance 🏎️

  • Stripe size-sorted files across parallel jobs (#5844), thanks @SanderMuller!
  • Keep input order of files withi...
Read more

2.2.2

Choose a tag to compare

@phpstan-bot phpstan-bot released this 05 Jun 09:01
e5cc34d

Improvements 🔧

Bugfixes 🐛

Function signature fixes 🤖

  • Correct xdebug filename/trace function return types in functionMap to include false/null (#5788), #14736

Internals 🔍

2.2.1

Choose a tag to compare

@phpstan-bot phpstan-bot released this 28 May 14:45
dea9c8f

Improvements 🔧

Bugfixes 🐛

Function signature fixes 🤖

2.2.0

Choose a tag to compare

@phpstan-bot phpstan-bot released this 28 May 08:41
b4cd983

Dive into details about this release on PHPStan's blog: PHPStan 2.2: Unsealed Array Shapes, Safer Array Keys, and More!. It explains all the changes and the motivation behind them.

Major new features 🚀

Bleeding edge 🔪

  • Sealed array shapes are truly sealed
    • Array shape like array{a: int, b: string} does not allow for extra keys and does not accept general arrays

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 🔧

Bugfixes 🐛

Internals 🔍