Repository navigation
Releases: phpstan/phpstan
Release list
2.3.1
Same performance, smaller package
We've heard your feedback. PHPStan 2.3.0 was chonky! It weighed 104 MB when downloaded and 268 MB after being unzipped in your vendor/.
Afer #6703, PHPStan 2.3.1 weighs just under 28 MB when downloaded and 87 MB unzipped.
Improvements 🔧
- Ship the turbo extension as a shared core plus a thin extension per PHP version (#6703), #15423
- Build Linux ZTS turbo binaries for PHP 8.3-8.5 too (#6706), #15422
- Allow PHP 8.6 in
phpstan/turbo(Composer PIE package) (#6705)
Bugfixes 🐛
- Keep the openssl cipher probe's warnings inside the probe (#6372), #15176, thanks @SanderMuller!
- Create the implicit throw point of a constructor on the new expression (#6687), #15396, thanks @janatjak!
- Read the updated value of consumed prefix mutations (#6692), #15411, thanks @drewmt!
- Cache a function reflection under the file that declares it (#6698), thanks @SanderMuller!
- Do not export what is declared inside a function or method body (#6699), thanks @SanderMuller!
Performance 🏎️
- Check original type for unresolvable types only when resolved type has one (#6675), thanks @Kocal!
- Keep the restored result cache out of forked workers' memory (#6686), #15387, thanks @janedbal!
- Save the result cache when a file has a parse error (#6694), thanks @SanderMuller!
Internals 🔍
- Start the cold run of the warm-rewrite test in a new second (#6697), thanks @SanderMuller!
2.3.0
This release fixes a whopping 75 issues! 🚀
Read about PHPStan 2.3.0 on the blog » I promise it's worth checking it out yourself, and not just letting your agent summarize it for you 😉 It contains a lot of interactive widgets with practical examples of the new features in action.
Major leap in performance. Back in December 2025 with PHPStan 2.1.33, as an example, analysing WordPress core took 60 seconds. With today's PHPStan 2.3.0, it takes under 8 seconds. Similar performance speedups can be observed across many codebases.
PHPStan Turbo speeds up PHPStan by 60% over the no-Turbo baseline.
Bleeding edge 🔪
- Generics: no more scalar generalization, multi-pass inference for
new Foo()from usages, aka "Bidirectional type narrowing" (#6332), #6732, #12704, #10419, #14647, #13431, #12601, #12490, #12420, #11835, #11435, #10290, #10289, #5741, #8031, #10783, #15147, #13325 - Detecting unused variables (#6330), #12789, #12012, #11483, #10202
- Unused variables: Report variable writes whose value never reaches a use, per array offset (#6334)
- Infer signatures of closures from where their values are sent (#6604, #6622), #11317, #3770
- Apply the effects of a closure's by-ref uses where it is invoked (#6610), #7751, #14248
- Infer the type of a
staticvariable from what the function body does with it (#6617, #6619), #7066
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 🔧
- Single-pass inside-out internals rewrite (#5857), #13944, #12207, #7155, #14396, #11953, #12780, #14999, #13334, #15004
- Implement
@pure-unless-parameter-passed(#6018, #6666), #11884, thanks @zonuexe! - Check preg_quote delimiters in array patterns (#6474), thanks @arpitjain099!
- Resolve
static::FOO_*andT::FOO_*PHPDoc types once the class is known (#6638), #4548, #11510
Bugfixes 🐛
- Keep property fetches on the receiver when a static method or static closure invalidates it (#6391), #13735, thanks @staabm and @SanderMuller
- Derive conditional guard types from the branch set difference (#6380), #13833, #9685, #7706, #14421
- Build a loop's back edge from its continue statements when the body end is unreachable (#6420), #14418, #13959, #11919, #1946
- Widen only the variables a loop can write when its scope converges (#6421), #12666
- Infer closure parameter types in array arguments (#6422), #6430, #11215
- Resolve generic parameter types from an array literal argument's skeleton before typing the closures nested in it (#6482), #15269
- Preserve conditional expression holders across more scope merges (#6385), #9628, #6830
- Narrow optional array offsets through
isset()conditions (#6382), #9426, #6379, #12786 - Do not read PHP_SBINDIR and PHP_BUILD_PROVIDER off the analysing machine (#6454), thanks @SanderMuller!
- Honour the composer.json
require.phpconstraint inScope::getPhpVersion()(#6476), #15270, thanks @staabm and @VincentLanglet! - Skip
@phpstan-assert, conditional return types and call effects when the nullsafe chain may short-circuit (#6486), #15016, #12925, thanks @VincentLanglet and @staabm! - NativeTypedClassConstantRule is scope php-version aware (#6497), #13133, thanks @staabm!
- Keep
neverinMutatingScope::intersectButNotNever()instead of widening it tonull(#6504), #15285 - Resolve "supported only on PHP X" checks from
Scope::getPhpVersion()instead of the injectedPhpVersion(#6496), #13133, thanks @staabm and @VincentLanglet! - Resolve property, trait constant, arrow function
neverand attribute PHP version checks fromScope::getPhpVersion()(#6510), #13133, thanks @staabm and @VincentLanglet! - Resolve the printf format parser's PHP version check from
Scope::getPhpVersion()(#6536), thanks @staabm! - Resolve PHP version checks in src/Type/Php extensions from
Scope::getPhpVersion()(#6551), thanks @staabm! - Resolve PHP version checks in remaining scope-aware extensions from
Scope::getPhpVersion()and forbid injectingPhpVersioninto them (#6563), #15287, thanks @staabm and @SanderMuller! - DeprecatedCastRule: Utilize
Scope::getPhpVersion()(#6600), thanks @staabm! - Do not cast floats past the int range, or NAN, where PHP does not (#6541)
- Ask
isCallable()of callable-like arrays and strings only where the answer is consumed (#6559), #15292 - Narrow the left side of
??to null in a non-true context only when its other values cannot satisfy it (#6581) - Memoize hasInstanceProperty() into its own cache (#6597)
- Keep an empty array next to an oversized array in a union (#6609)
- Do not report a private method overriding a private trait method as unused (#6191), #12201, thanks @Jean-Beru!
- Keep the narrowed bound of a template type that
TemplateTypeHelper::resolveTemplateTypes()maps to itself (#6613), #15321, thanks @staabm! - Do not remember a void equality assertion statement as true when its arguments contain an impure call (#6625), #15328
- Compare the element type of a variadic by-ref parameter against its out type (#6227), #15066, thanks @SanderMuller!
- Keep unresolved template arguments of different sites apart, solve covariant ones like Hack (#6650), #15331
Performance 🏎️
- Turbo now shadows majority of the analyser engine (#6499, #6503, #6506, #6508, #6509, #6511, #6521, #6523, #6530, #6532, #6533, #6535)
- Resolve constant offsets on constant arrays through the key index (#6442)
- Speed up enum-case removal, finite type counting, large unions and loop widening of shapes (#6443)
- Memoize
PhpMethodReflection::getName()and return the right operand on aTypeCombinatorCachememo hit (#6489) - Harden Turbo traversal, arena, and iterable parity (#6538)
- Build smaller turbo binaries (#6552)
- Pass immutable array arguments non-refcounted through
zv::Args(#6561), thanks @zonuexe! - Cheaper file cache, type memo bookkeeping and expression-key lookups (#6568)
- Share one NamespaceUses between the name scopes of a file (#6583), #15304
- Share one N...
2.2.17
This is the last release in 2.2.x series. Look forward to PHPStan 2.3.0 which is going to be released next week with the following highlights:
- Massive leap in performance (again!)
- Generics improvements (bidirectional type narrowing which closes #6732 and dozens of duplicate issues)
- Unused variables detection
Here's what new and changed in PHPStan 2.2.17:
Improvements 🔧
- Compile PHP 8.6 turbo binaries against 8.6.0RC2 (#6599)
- Build Linux ZTS turbo binaries for PHP 8.6+ (#6657)
- Point method visibility errors at the method, not its first attribute (#6630), #14398, thanks @Cayan!
Bugfixes 🐛
- Cache parsed ASTs behind the path routing, one cache per parser (#6569), #15231, thanks @SanderMuller!
- Keep optional groups optional within a matched regex alternation branch (#6596), #15297
- Do not track string keys of an unpacked non-literal expression in
DuplicateKeysInLiteralArraysRule(#6635), #15295, thanks @VincentLanglet and @staabm!
Performance 🏎️
- Cache a class's ancestors without the class itself (#6593), thanks @SanderMuller!
Function signature fixes 🤖
Internals 🔍
- Load dead-code-detector in self-analysis only on PHP 8.2 and later (#6591), thanks @SanderMuller!
- Mutation testing: diff against a configured branch, cover only the changed files (#6664)
2.2.16
Bugfixes 🐛
- Treat possible Error throws as an effect of an expression statement again (phpstan/phpstan-src@6a09253)
- Keep a by-ref writeback's native type only when the written-back type fits it (#6564), thanks @SanderMuller!
- Report worker peak memory when the result cache is used (#6576), thanks @alfredbez!
- Compare ternary arm values, not their truthiness, in exact narrowing contexts (#6580), #15307, #15226
- Keep the normalized branches of a traversed ConditionalType normalized, Narrow the parameter for nested conditions on the same parameter (#6586), #15310, #15296
Internals 🔍
- Fix flaky tests (#6361)
2.2.15
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-dsv1 vs. v2 (#6250), #14539, thanks @simPod!- only
ext-dsandext-couchbaseare currently supported - PHPStan uses the extension version constraint from composer.json
- only
- Check for property hooks being pure/impure (#6246), thanks @AJenbo!
- Add Error class to
uncheckedExceptionClassesby default (phpstan/phpstan-src@2fd897a), #15271 - Resolve conditional
@throwstypes 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_FAILUREinfilter_input(),filter_var_array()andfilter_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
NameResolvererrors intoParserErrorsExceptionso they are attributed to the file they come from (#6455), #15252 - Write the offset instead of intersecting with
HasOffsetValueTypewhen overwriting anArrayDimFetch(#6456), #15246 - Merge sub-expression throw points, impure points,
hasYieldand 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
foreachshape 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-linksetExistingOffsetValueType()shortcut (#6466), #15245, thanks @staabm! - Compare literal array offsets as the keys they become (#6466), #15245, thanks @staabm!
- Detect overflowing
<<bounds, keepfloatforPHP_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
throwexpression 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()inarray_fill_keysandarray_combinereturn 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 aConstantArrayTypewhen separator, string and limit are all constant (#6123), #15013, thanks @VincentLanglet and @staabm! - Un-prefix
Filter\andPDO\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
tracekey toerror_get_last()(#6470), thanks @janedbal! - Describe
Random\Randomizerarray, bytes and integer methods with dedicated dynamic return type extensions (#6469), #15256, thanks @VincentLanglet and @staabm! - Correct GearmanClient
uniqueparameters (#6241), thanks @donatj! - Allow
FILTER_THROW_ON_FAILUREin$optionsoffilter_var()andfilter_input()(#6513), #15007 - Because recent
jetbrains/phpstorm-stubsupdate added@throws ...Errorfor 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()onSpecifiedTypesto replace FAUX function call workarounds (#5769), #14705, thanks @VincentLanglet and @staabm! - Improve TypeCombinator::addNull (#6493), thanks @VincentLanglet!
- Keep
neverinMutatingScope::intersectButNotNever()instead of widening it tonull(#6507)
- Keep
- Do not create a throw point for void returned by dynamic throw type extensions (#6515)
- Replace PrintfHe...
2.2.14
Improvements 🔧
- Apply
finallyscope changes to try-catch exit points and check by-ref return types afterfinally(#6393), #13338 - Fix PHP 8.6 deprecation in hoa/consistency (#6405), thanks @SanderMuller!
Bugfixes 🐛
- Compare conditional expressions in
MutatingScope::equals()(#6344), #15157, thanks @janedbal! - Fix
containsNull()for union withnull&T of mixed(#6390), thanks @vojtech-dobes! - Do not resolve include paths through a stream wrapper that is not registered (#6397), #15192
- Do not treat
mixedtype arguments as compatible both ways when both generic types are parameterized (#6398), #15198 - Fix union of template array-key with false losing the template (#6376), #13374, #13192, #10871, #8268, #7423, #7279, #7049, thanks @calebdw!
- Fix false positive comparing identical generic types below level 8 (#6392), #13876, #12984, #12008, #11041, #10698, #9377, #9096, thanks @calebdw!
pcntl_exec()is not supported by blackfire (#6409), thanks @staabm!UsedNamesRule: reset imported names at everynamespacedeclaration instead of keying them by namespace name (#6413), #15215- Derive per-arm conditional expressions from overlapping ternary arm types (#6381), #7905
- Record needle-implies-true conditional expression for in_array() assignments (#6381), #9752
- Propagate conditional expressions through derived assignments (#6381), #13054
- Do not report
?? null/??= nullas unnecessary when evaluating the right side has side effects (#6418), #15134, thanks @VincentLanglet and @staabm!
Performance 🏎️
- Reduce repeated work when matching ignored errors (#6374), thanks @zonuexe!
- Do not look up class reflection for properties without hooks (#6396)
- Share the directory walk between the analyse and the scan file finder (#6396)
- Read the exported PHPDoc scope off the AST instead of through FileTypeMapper (#6396)
- Memoize
ClassReflection::getName()(#6406) - Inline single-return getters when building the PHAR (#6406, #6412)
- Remove a union of values from a set in one pass (#6427)
- Key types by their value where
describe()was standing in for it (#6427) - Answer reflection cache misses without a failing
include()(#6430)
Function signature fixes 🤖
Internals 🔍
2.2.13
Result cache finally becomes usable for monorepo setups. It knows exactly what needs to be reanalysed when PHP files included via "type": "path" Composer dependencies are edited and also when files in scanFiles/scanDirectories are edited. 🔍✏️
Many result cache bugs were squashed 🐛 and the serialization format changed to a much more efficient one. 🏎️
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 🔧
- Interpret array shape keys as
@templatetypes when a template of that name is in scope (#6322), #15145- Allows types like
array{TKey: string}with@template TKeyabove
- Allows types like
Bugfixes 🐛
- Do not bind a template type to an argument absorbed by another union member (#6341), #8441
- Normalize the result cache meta before comparing it with the restored one (#6346), #15125, #15152
- Let OpenSslCipherMethodsProvider contribute its own result cache meta (#6338), thanks @SanderMuller!
- Resolve template defaults referencing other templates in composite types (#6329), thanks @calebdw!
- Rename the result cache into place instead of writing it over the old one (#6349, #6353), thanks @SanderMuller!
- Do not locate symbols declared by the
symfony/polyfill-*packages bundled with PHPStan itself (#6351), #15150 - Stop interning TypeCombinator results in the turbo extension (#6355), #15151
- Cover a file newly appearing in a scanDirectories directory (#6352), #15149
- Fixed various bugs where the result cache could become stale (#6357)
- Fix result cache invalidation with
@varreferenced classes (#6343), thanks @Mika-! - Re-analyse the files with errors when a Composer package changes (#6362), #15164
- Do not let the exactness of
new Foo()reach an inferred template argument (#6363), #15166 - Invalidate the result cache when any extension file changes (#6368)
Performance 🏎️
- PHPStan always runs with OPCache (#6324, #6325)
- Strip run-time type checks from PHPStan's own code with a turbo optimizer pass (phpstan/phpstan-src@3788169)
- Store the result cache in a framed
serialize()format instead of a var_export'd PHP file (#5982), thanks @SanderMuller! - Edited PHP files from
scanFilesandscanDirectoriesnow properly invalidate files dependent on them in the result cache #6352- Previously they invalidated the whole result cache and full analysis was necessary, this is no longer the case
- Result cache now notices edited PHP files in Composer dependencies added via
"repositories"with"type": "path"(#6356)- Previously the result cache didn't notice this edit so it became stale and you had to run
clear-result-cacheto get fresh results
- Previously the result cache didn't notice this edit so it became stale and you had to run
- HashFunctionsReturnTypeExtension: init hash-algorithm list lazily (#6345), thanks @staabm!
- Keep the result cache when the turbo extension is switched on or off (#6335), thanks @SanderMuller!
- Track scanned files as file dependencies instead of invalidating the whole result cache (#6352), #15149
- Do not invalidate the result cache when
tmpDirchanges (#6359), thanks @SanderMuller!
Function signature fixes 🤖
- Give
password_get_info()the array shape it always returns (#6299), thanks @SanderMuller!
Internals 🔍
2.2.12
Improvements 🔧
- Cap the detected CPU core count by the cgroup CPU quota (#6317)
- Implement worker auto-scaler (#6256), thanks @AJenbo!
Bugfixes 🐛
- Look up the stub PHPDoc of a class only when it is read (#6316), #15120
- Export PHPDoc name scopes without resolving
@templatebounds (#6316) - Read property virtuality off the native reflection when exporting nodes (#6316)
- Keep the turbo code that runs before the Composer autoloader polyfill-free (#6319), #15137
- End forked workers with _exit() instead of PHP's full teardown (#6320), #15138, #15142
Performance 🏎️
- Update phpdoc-parser (#6321)
- Lexer: extract matches with PREG_PATTERN_ORDER (~40% faster lexing) (phpstan/phpdoc-parser#313), thanks @JanTvrdik!
2.2.11
Improvements 🔧
- Add a
result-cache-infocommand reporting how the nextanalysewould use the result cache (#6312), #15135
Bugfixes 🐛
- Fix musl detection causing turbo to fail on some systems (#6308), thanks @AJenbo!
- Update phpdoc-parser (#6314)
- Fix three ways a valid PHPDoc is read or written back wrong (phpstan/phpdoc-parser@d551e9e)
- Read
Foo & .5as an intersection, not as a reference (phpstan/phpdoc-parser@58390a4)
- Cover the arena running out of shared memory, and workers dying by signal (#6313), #15131
2.2.10
This release brings improved performance and reduced memory consumption, mainly thanks to:
- Forking parallel workers where available:
- Instead of spawning processes with
proc_open(), they are forked withpcntl_fork(), saving time to bootstrap PHPStan - This requires PHPStan Turbo extension (already present if you install PHPStan with Composer) and non-Windows OS
- Instead of spawning processes with
- Deduped objects held in memory by BetterReflection
- Turbo extension-accelerated directories symbols scanning which allowed us to remove caching of this data and locking in worker processes
Feel free to comment how PHPStan 2.2.9 vs. 2.2.10 perform on your project! 🚀
Bleeding edge 🔪
- Check written case of single-part class names imported with use statements (#6271), #12827, thanks @janedbal!
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 🔧
- Notify in CI when a full analysis ran without a pre-existing result cache for more than 60 seconds (#5954), #14881, thanks @staabm!
- Emit node callbacks after the node's results are stored and drop FNSR introduced in 2.1.34 (#6248)
- Report peak memory per process instead of a summed total (#6297)
Bugfixes 🐛
- Return the operand from union() for equal array operands, not just identical ones (#6257), thanks @AJenbo!
- Preserve surviving offsets when popping or shifting a list (#6274)
- Account for deduplicated trait errors per using-class context (#6280), #14932
- Revert "Consult bootstrap-registered custom autoloaders only after the static source locators (#6069)" (#6292), #15102
- Run StubFilesExtensions only after bootstrapFiles have been executed (#6284), #15120
Performance 🏎️
- Use LruCache for the other three least-recently-used caches (#6240), thanks @SanderMuller!
- Replay the recorded fixpoint pass instead of repeating the final loop walk (#6249)
- Fork parallel workers (instead of spawning) whenever the turbo extension is active (#6260)
- Intern TypeCombinator results in turbo (#6261), thanks @AJenbo!
- Bound ObjectType's static caches with a shared LRU over description keys (#6289), #15119
- Update BetterReflection
- Share inherited method reflections and their types across classes (ondrejmirtes/BetterReflection@be9c3a9)
- Parse cached value expressions lazily (ondrejmirtes/BetterReflection@fb1f47c)
- Scan directories natively, and drop the cache and lock behind it (#6304)
Function signature fixes 🤖
- Clean out redundant stub overwrites (#6243), thanks @AJenbo!
- Make SensitiveParameterValue generic (#6272), thanks @JanTvrdik!
- Fix simplexml_import_dom() parameter type on PHP 8.4 (#6290), thanks @janedbal!
Internals 🔍
- Fix incorrect casing (#6244), thanks @AJenbo!
- Introduce StmtHandler (#6247)
- Feed engine gatherers from NodeScopeResolver frames instead of wrapping node callbacks (#6258)
- Replay scope-deriving mutators in NodeCallbackScope answers (#6259)
- Ignore the turbo version constant in the typos check (#6270), thanks @SanderMuller!
- Migrate a deprecated isSubclassOf call (#6268), thanks @AJenbo!
- Guard against null in getNameScope (#6267), thanks @AJenbo!
- Remove unused variables (#6266), thanks @AJenbo!
- CS for build/PHPStan/ (phpstan/phpstan-src@bbd64b4)
- Run bootstrapFiles per forked worker instead of inheriting the parent's (#6264)
- phar.yml - get quicker to commit step (phpstan/phpstan-src@ccbde4b)
- Price enum case values through InitializerExprTypeResolver in EnumSanityRule (#6275)
- Extract function-call scope effects into FuncCallScopeEffectsHelper (#6279)
- Cover the facade-alias shape with an e2e project (#6265), thanks @SanderMuller!
- Use early exit when collecting the registered class loaders (#6282), thanks @SanderMuller!
- Cover the loader shapes the reverted autoloader attempts broke (#6293), thanks @SanderMuller!