This release fixes 55 issues! π
Bleeding edge πͺ
- Report invalid
DateIntervalconstructor arguments at analysis time (#5587), #14442, thanks @staabm and @VincentLanglet! - Report impure method overriding pure parent method in
MethodSignatureRule(#5584), #14563, thanks @VincentLanglet and @staabm! - Validate
define()andconstvalues against explicit types indynamicConstantNames(#5648), #14600, thanks @staabm and @VincentLanglet!
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 π§
- Don't report "no value type specified in iterable type array&callable" (#5565), thanks @staabm!
- Resolve method reflection for dynamic static calls (
$var::method()) to enable purity and side-effect checking (#5572), #14557, #5020, thanks @VincentLanglet and @staabm! - Track more expressions (#5596), #12517, #6486, #9155, thanks @VincentLanglet!
- Detect private promoted properties whose only reads are self-writes via
new self()(#5599), #14573 - Report wrong types being passed to
array&callabletype (#5573), #14549, thanks @VincentLanglet and @staabm! - Infer
numeric-stringforDateInterval::format('%a')when interval comes fromdiff()(#5674), #1452, thanks @VincentLanglet and @staabm!
Bugfixes π
- Recurse into parent expression in
IssetCheckandMutatingScope::issetCheckwhen property has propagated error (#5569), #14555 - Fix oversized-array self-rejection in
optimizeConstantArrays(phpstan/phpstan-src@9743346) - Update jetbrains/phpstorm-stubs (#5576), #14559, thanks @bitwise-operators!
- Track
$arr[$key]existence acrossarray_search/array_find_keyvia conditional expression holders (#5552), #14537, thanks @staabm and @VincentLanglet! - Do not narrow array to empty when
array_find_key()returns null (#5693), #14630 - Fix implode losing non-empty-string when ConstantArrayType has all-optional keys (#5578), #14558, thanks @VincentLanglet and @staabm!
- Narrow
DateInterval->daysafterDateTimeInterface->diff()(#5588), #14428, thanks @staabm! - Treat
*as assignment suppression insscanf/fscanfplaceholder counting (#5586), #10260, thanks @staabm and @VincentLanglet! - Do not prefix anything in resources/ when building phpstan.phar (phpstan/phpstan-src@5c28048)
- Walk ancestors for stub method PHPDoc on built-in classes without their own stub entries (#5695), #14632, thanks @staabm!
- Isolate alternation branches in
RegexGroupParser::walkGroupAst()to prevent non-empty/non-falsy state bleeding (#5602), #14575, thanks @staabm and @VincentLanglet! - Widen empty
ConstantArrayTypetoarraywhen resolving dynamic constant types (#5606), #8526, thanks @VincentLanglet and @staabm! - Fix counting
*scanf()format string placeholders (#5594), #14567, thanks @hakre! - Do not report
maybeinRandomIntParametersRulewhen either argument is an unboundedIntegerRangeType(#5622), #14468, thanks @staabm and @VincentLanglet! - Assign proper types for
$argcand$argvinglobalstatements (#5623), #12392, thanks @staabm and @VincentLanglet! - Do not propagate
isAlwaysTerminatingfrom immediately-invoked callable arguments to the outer call (#5604), #14582, thanks @VincentLanglet! - Resolve
ConditionalTypewhen subject-target relationship is deterministic despite containing template types (#5631), #11894, #8048, thanks @VincentLanglet and @staabm! - Return
nullfromArgumentsNormalizer::reorderArgs()when positional args after named args create holes beyond parameter count (#5637), #14596, thanks @staabm and @VincentLanglet! - Collect all remaining callable parameter types for variadic closure parameters instead of using only the matching index (#5634), #9240, thanks @VincentLanglet and @staabm!
- Switch HasMethodType/HasPropertyType from ObjectTypeTrait to MaybeObjectTypeTrait (#5605), #8217, thanks @VincentLanglet and @staabm!
- Augment
BooleanAndfalsey andBooleanOrtruthy type narrowing when left and right conditions narrow different expression keys (#5595), #14566, #13061, #7259, thanks @VincentLanglet! - callable-array intersection type is a constant array (#5647)
- Fix infinite recursion in specifyTypesForCountFuncCall with mixed TypeSpecifierContext (#5653), #14605
- Do not report
non-falsy-string == 0as always false inAccessoryNonFalsyStringType::looseCompare()(#5654), #14606, thanks @VincentLanglet and @staabm! - Prevent creation of IntersectionType with just HasOffsetValueType accessories (phpstan/phpstan-src@fa4e7d2), #14604
- Prevent issue with accessory-only IntersectionType (phpstan/phpstan-src@f2af15b)
- Re-check scalar types after integer range expansion in
TypeCombinator::union(#5660), #14610, thanks @staabm and @VincentLanglet! - Respect
@throws voidongetIterator()when determining foreach Traversable throw points (#5666), #6833, thanks @staabm and @VincentLanglet! - Check inner union types before delegating to
isSubTypeOfforLateResolvableTypeinUnionType::isSuperTypeOf()(#5645), #10942, thanks @staabm and @VincentLanglet! - Use pre-args scope for value types in array_push/array_unshift (#5579), #13510, thanks @predictor2718!
- Use before-scope for evaluating
array_spliceargument types (#5682), #13510, thanks @VincentLanglet and @staabm! - Fix: property.notFound in chained isset() with checkDynamicProperties (#5562), #13539, thanks @predictor2718!
- Invalidate property types after dynamic method calls (#5679), #3831, thanks @VincentLanglet and @staabm!
- Skip class name case check for type hints using explicit
use ... asaliases (#5671), #14617, thanks @VincentLanglet and @staabm! - Skip non-discriminating guards in
createConditionalExpressionseven when target is not tracked in the other scope (#5676), #14595, thanks @staabm and @VincentLanglet! - Preserve
TemplateTypeinIntersectionType::shuffleArray()when intersection is already a list (#5694), #14631 - Fix another shuffle() variant (#5696), thanks @staabm!
Performance ποΈ
- Lazily initialize AggregateSourceLocator to speedup bootstrapping (#5577), thanks @staabm!
- PhpFileCleaner: Use strcspn instead of regex for fast-skip in clean() (#5600), thanks @staabm!
- Cap cumulative unroll factor when nesting unrolled constant-array foreach (#5614), #14590
- DateFunctionReturnTypeHelper: prevent unnecessary
TypeCombinator::union()(#5629), thanks @staabm! - Memoize
ArrayType::isList()(#5680), thanks @staabm!
Function signature fixes π€
- Fix #14499: Mark Lua::__construct $lua_script_file parameter as optional (#5571), #14499, thanks @predictor2718!
- More concrete return type for
opcache_get_configuration(#5424), thanks @devnix! - Conditional return type for
SQLite3Result::fetchArray()(#3080), thanks @devnix! - Some metadata fixes for SPL classes (#5574), thanks @bitwise-operators!
- Mark
class_exists,interface_exists,trait_exists, andenum_existsas having no side effects in function metadata (#5607), #8579, thanks @VincentLanglet and @staabm! - Add multi-variant overloads for
PDOStatement::fetchAll()in function signature map (#5630), #5509, thanks @VincentLanglet and @staabm! - Return
list<mixed>fromPDOStatement::fetchAll()(#5643), #11889, thanks @staabm and @VincentLanglet!
Internals π
- Add bench for PhpDocInheritanceResolver speedup from #4829 (phpstan/phpstan-src@d34f7cc)
- Added regression test (#5585), #9004, thanks @staabm!
- Remove dead code from FileExcluder (#5598), thanks @staabm!
- Compiler - update Box + dependencies (#5601)
- Simplify compiler/box/composer.json (phpstan/phpstan-src@37e8fe0)
- Extract
Type::makeListMaybe()for sort functions that drop list-ness (#5611) - Extract
Type::mapValueType(callable)for "same keys, transformed values" (#5611) - Extract
Type::changeKeyCaseArray(?int)forarray_change_key_case(#5611) - Extract
Type::filterArrayRemovingFalsey()forarray_filterno-callback path (#5611) - Extract
Type::mapKeyType(callable)and use it alongsidemapValueTypein NodeScopeResolver (#5611) - Add Type::makeAllArrayKeysOptional() for preg_replace* array fast path (#5611)
- Extract
Type::toBitwiseNotType()for~$x(#5612) - Extract
Type::toGetClassResultType()forget_class($x)(#5612) - Extract
Type::toClassConstantType()for$x::class(#5612) - Extract
Type::toObjectTypeForInstanceofCheck()forinstanceofRHS (#5612) - Extract
Type::toObjectTypeForIsACheck()foris_a($x, $class, $allowString)(#5612) - Inline one-line wrappers around polymorphic Type methods (#5613)
- Test result-cache restore does not trigger reflection (#5617), thanks @staabm!
- Test result-cache restore does not trigger reflection in all 1st party extensions (#5618), thanks @staabm!
- Remove dead code in StrContainingTypeSpecifyingExtension (#5626), thanks @staabm!
- Merge NSRT and rule test fixtures for bug-14582 into a single file (#5604), #14582, thanks @VincentLanglet!
- Introduce
MutatingScope::getCallableParameterType(#5635), thanks @VincentLanglet! - Introduce MaybeStringTypeTrait (#5642), thanks @VincentLanglet!
- Added regression test (#5652), #14569, thanks @staabm!
- IntersectionType::toPhpDocNode - check empty types (phpstan/phpstan-src@bfa881c)
- Introduce Process interface and ProcessBase for parallel workers (#5663)
- Extract WorkerRunner from WorkerCommand (#5663)
- Add pcntl_fork() parallel worker path (#5663)
- Introduce ProcessPromise interface for the PHPStan Pro worker (#5663)
- Extract FixerWorkerRunner from FixerWorkerCommand (#5663)
- Add pcntl_fork() PHPStan Pro worker path (#5663)
- Print parallel worker mechanism via DiagnoseExtension (#5663)
- Experiment: fork parallel workers via
pcntl_fork()(phpstan/phpstan-src#5663)- Mostly broken because of PHAR file pointer shared between process forks
- Opt-in behaviour with env var
PHPSTAN_PARALLEL_FORK=1 - Looking for an idea for a fix from the community
- Add regression test for circular class constant PHPDoc type references (#5685), #9172, thanks @VincentLanglet and @staabm!