From d8bd9d2c9b372a0b664c809f3c1af10b651efa7f Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 5 May 2026 08:05:39 +0000 Subject: [PATCH 1/4] Detect private promoted properties whose only reads are self-writes via `new self()` - Track whether each property read is a "true read" vs a "self-write" (property passed to the same constructor parameter of the same class) - After processing all usages, if a promoted property's only reads are self-writes, mark it as unread so the "never read, only written" error is reported - Handles new self(), new static(), and new ClassName() for the same class - Named arguments are correctly matched by parameter name - Properties passed to different parameters or different classes are not affected - Add baseline entries for 3 new findings in PHPStan's own code --- phpstan-baseline.neon | 18 ++ .../DeadCode/UnusedPrivatePropertyRule.php | 56 +++++ .../UnusedPrivatePropertyRuleTest.php | 57 +++++ .../PHPStan/Rules/DeadCode/data/bug-14573.php | 229 ++++++++++++++++++ 4 files changed, 360 insertions(+) create mode 100644 tests/PHPStan/Rules/DeadCode/data/bug-14573.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ec7779bfbed..705adf671de 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -519,6 +519,18 @@ parameters: count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php + - + rawMessage: "Property PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedPropertyPrototypeReflection::$propertyName is never read, only written." + identifier: property.onlyWritten + count: 1 + path: src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php + + - + rawMessage: "Property PHPStan\\Reflection\\Type\\UnionTypeUnresolvedPropertyPrototypeReflection::$propertyName is never read, only written." + identifier: property.onlyWritten + count: 1 + path: src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php + - rawMessage: 'Doing instanceof PHPStan\Type\Constant\ConstantBooleanType is error-prone and deprecated. Use Type::isTrue() or Type::isFalse() instead.' identifier: phpstanApi.instanceofType @@ -591,6 +603,12 @@ parameters: count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + - + rawMessage: "Property PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeHelper::$universalObjectCratesClasses is never read, only written." + identifier: property.onlyWritten + count: 1 + path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + - rawMessage: 'Doing instanceof PHPStan\Type\Constant\ConstantBooleanType is error-prone and deprecated. Use Type::isTrue() or Type::isFalse() instead.' identifier: phpstanApi.instanceofType diff --git a/src/Rules/DeadCode/UnusedPrivatePropertyRule.php b/src/Rules/DeadCode/UnusedPrivatePropertyRule.php index 7d2ccc73280..1e797b06cbf 100644 --- a/src/Rules/DeadCode/UnusedPrivatePropertyRule.php +++ b/src/Rules/DeadCode/UnusedPrivatePropertyRule.php @@ -7,7 +7,9 @@ use PHPStan\DependencyInjection\AutowiredParameter; use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\ClassPropertiesNode; +use PHPStan\Node\ClassPropertyNode; use PHPStan\Node\Property\PropertyRead; +use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider; use PHPStan\Rules\Rule; @@ -120,6 +122,7 @@ public function processNode(Node $node, Scope $scope): array 'node' => $property, 'onlyReadable' => $property->isReadable() && !$property->isWritable(), 'onlyWritable' => $property->isWritable() && !$property->isReadable(), + 'hasTrueRead' => $alwaysRead, ]; } @@ -194,6 +197,7 @@ public function processNode(Node $node, Scope $scope): array if (!$classType->isSuperTypeOf($fetchedOnType)->no()) { if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = true; + $properties[$propertyName]['hasTrueRead'] = true; } else { $properties[$propertyName]['written'] = true; } @@ -204,6 +208,7 @@ public function processNode(Node $node, Scope $scope): array if (!$classType->isSuperTypeOf($fetchedOnType)->no()) { if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = true; + $properties[$propertyName]['hasTrueRead'] = true; } else { $properties[$propertyName]['written'] = true; } @@ -213,12 +218,25 @@ public function processNode(Node $node, Scope $scope): array if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = true; + if (!$this->isPropertySelfWrite($usageScope, $propertyName, $propertyNode, $classReflection->getName())) { + $properties[$propertyName]['hasTrueRead'] = true; + } } else { $properties[$propertyName]['written'] = true; } } } + foreach ($properties as $propertyName => $data) { + if (!$data['read'] || $data['hasTrueRead']) { + continue; + } + if (!$data['node']->isPromoted()) { + continue; + } + $properties[$propertyName]['read'] = false; + } + [$uninitializedProperties] = $node->getUninitializedProperties($scope, []); $errors = []; @@ -270,4 +288,42 @@ public function processNode(Node $node, Scope $scope): array return $errors; } + private function isPropertySelfWrite( + Scope $usageScope, + string $propertyName, + ClassPropertyNode $propertyNode, + string $className, + ): bool + { + if (!$propertyNode->isPromoted()) { + return false; + } + + $callStack = $usageScope->getFunctionCallStackWithParameters(); + if ($callStack === []) { + return false; + } + + $lastCall = $callStack[count($callStack) - 1]; + [$calleeReflection, $parameterReflection] = $lastCall; + + if (!$calleeReflection instanceof MethodReflection) { + return false; + } + + if ($calleeReflection->getName() !== '__construct') { + return false; + } + + if ($calleeReflection->getDeclaringClass()->getName() !== $className) { + return false; + } + + if ($parameterReflection === null) { + return false; + } + + return $parameterReflection->getName() === $propertyName; + } + } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php index 0214ecaaadd..cc98e1a27a8 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php @@ -409,4 +409,61 @@ public function testBug6777(): void $this->analyse([__DIR__ . '/data/bug-6777.php'], []); } + #[RequiresPhp('>= 8.0.0')] + public function testBug14573(): void + { + $this->alwaysWrittenTags = []; + $this->alwaysReadTags = []; + + $tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties'; + + $this->analyse([__DIR__ . '/data/bug-14573.php'], [ + [ + 'Property Bug14573\Foo::$test is never read, only written.', + 8, + $tip, + ], + [ + 'Property Bug14573\Bar::$b is never read, only written.', + 22, + $tip, + ], + [ + 'Property Bug14573\Baz::$a is never read, only written.', + 41, + $tip, + ], + [ + 'Property Bug14573\Baz::$b is never read, only written.', + 41, + $tip, + ], + [ + 'Property Bug14573\WithNewStatic::$test is never read, only written.', + 88, + $tip, + ], + [ + 'Property Bug14573\WithNewClassName::$test is never read, only written.', + 102, + $tip, + ], + [ + 'Property Bug14573\WithNamedArgument::$a is never read, only written.', + 135, + $tip, + ], + [ + 'Property Bug14573\WithNamedArgument::$b is never read, only written.', + 135, + $tip, + ], + [ + 'Property Bug14573\MultipleReadsOnlySelfWrite::$test is never read, only written.', + 177, + $tip, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/DeadCode/data/bug-14573.php b/tests/PHPStan/Rules/DeadCode/data/bug-14573.php new file mode 100644 index 00000000000..5ecde4ad57b --- /dev/null +++ b/tests/PHPStan/Rules/DeadCode/data/bug-14573.php @@ -0,0 +1,229 @@ += 8.0 + +namespace Bug14573; + +class Foo +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): self + { + return new self($this->test); + } + +} + +class Bar +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self($this->a, $this->b); + } + + public function getA(): int + { + return $this->a; + } + +} + +class Baz +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self($this->a, $this->b); + } + +} + +class Quux +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self($this->b, $this->a); + } + +} + +class WithAdditionalRead +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): self + { + return new self($this->test); + } + + public function getTest(): int + { + return $this->test; + } + +} + +class WithNewStatic +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): static + { + return new static($this->test); + } + +} + +class WithNewClassName +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): self + { + return new WithNewClassName($this->test); + } + +} + +class DifferentPropertyPassedToSameParam +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self($this->b, $this->a); + } + + public function getA(): int + { + return $this->a; + } + +} + +class WithNamedArgument +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self(b: $this->b, a: $this->a); + } + +} + +class WithNamedArgumentSwapped +{ + + public function __construct(private int $a, private int $b) + { + } + + public function doFoo(): self + { + return new self(b: $this->a, a: $this->b); + } + +} + +class PassedToOtherClassConstructor +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): Foo + { + return new Foo($this->test); + } + +} + +class MultipleReadsOnlySelfWrite +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): self + { + return new self($this->test); + } + + public function doBar(): self + { + return new self($this->test); + } + +} + +class MixedSelfWriteAndTrueRead +{ + + public function __construct(private int $test) + { + } + + public function doFoo(): self + { + return new self($this->test); + } + + public function getTest(): int + { + return $this->test; + } + +} + +class SelfWriteInNonConstructorCall +{ + + public function __construct(private int $test) + { + } + + public function doFoo(int $test): self + { + $this->doBar($this->test); + return new self($this->test); + } + + private function doBar(int $test): void + { + } + +} From 7517f35df05a7d9570855b8095c72125b32ff0e2 Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Tue, 5 May 2026 08:41:44 +0000 Subject: [PATCH 2/4] Remove unused $propertyName from IntersectionType/UnionType UnresolvedPropertyPrototypeReflection Co-Authored-By: Claude Opus 4.6 --- phpstan-baseline.neon | 17 ----------------- ...ypeUnresolvedPropertyPrototypeReflection.php | 5 ++--- ...ypeUnresolvedPropertyPrototypeReflection.php | 5 ++--- src/Type/IntersectionType.php | 6 +++--- src/Type/ObjectType.php | 4 ++-- src/Type/UnionType.php | 6 +++--- 6 files changed, 12 insertions(+), 31 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 705adf671de..74e554f9f27 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -519,17 +519,6 @@ parameters: count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - - - rawMessage: "Property PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedPropertyPrototypeReflection::$propertyName is never read, only written." - identifier: property.onlyWritten - count: 1 - path: src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php - - - - rawMessage: "Property PHPStan\\Reflection\\Type\\UnionTypeUnresolvedPropertyPrototypeReflection::$propertyName is never read, only written." - identifier: property.onlyWritten - count: 1 - path: src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php - rawMessage: 'Doing instanceof PHPStan\Type\Constant\ConstantBooleanType is error-prone and deprecated. Use Type::isTrue() or Type::isFalse() instead.' @@ -603,12 +592,6 @@ parameters: count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - - rawMessage: "Property PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeHelper::$universalObjectCratesClasses is never read, only written." - identifier: property.onlyWritten - count: 1 - path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - rawMessage: 'Doing instanceof PHPStan\Type\Constant\ConstantBooleanType is error-prone and deprecated. Use Type::isTrue() or Type::isFalse() instead.' identifier: phpstanApi.instanceofType diff --git a/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php b/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php index 51e6ccaf469..a0c28b66f2d 100644 --- a/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php +++ b/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php @@ -18,7 +18,6 @@ final class IntersectionTypeUnresolvedPropertyPrototypeReflection implements Unr * @param UnresolvedPropertyPrototypeReflection[] $propertyPrototypes */ public function __construct( - private string $propertyName, private array $propertyPrototypes, ) { @@ -30,7 +29,7 @@ public function doNotResolveTemplateTypeMapToBounds(): UnresolvedPropertyPrototy return $this->cachedDoNotResolveTemplateTypeMapToBounds; } - return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes)); + return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes)); } public function getNakedProperty(): ExtendedPropertyReflection @@ -50,7 +49,7 @@ public function getTransformedProperty(): ExtendedPropertyReflection public function withFechedOnType(Type $type): UnresolvedPropertyPrototypeReflection { - return new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); + return new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); } } diff --git a/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php b/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php index b28625e3c33..f5d6b7dd9b2 100644 --- a/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php +++ b/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php @@ -18,7 +18,6 @@ final class UnionTypeUnresolvedPropertyPrototypeReflection implements Unresolved * @param UnresolvedPropertyPrototypeReflection[] $propertyPrototypes */ public function __construct( - private string $propertyName, private array $propertyPrototypes, ) { @@ -29,7 +28,7 @@ public function doNotResolveTemplateTypeMapToBounds(): UnresolvedPropertyPrototy if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } - return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes)); + return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes)); } public function getNakedProperty(): ExtendedPropertyReflection @@ -50,7 +49,7 @@ public function getTransformedProperty(): ExtendedPropertyReflection public function withFechedOnType(Type $type): UnresolvedPropertyPrototypeReflection { - return new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); + return new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); } } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index f5dceab6006..158b9183303 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -615,7 +615,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember return $propertyPrototypes[0]; } - return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasInstanceProperty(string $propertyName): TrinaryLogic @@ -648,7 +648,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla return $propertyPrototypes[0]; } - return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasStaticProperty(string $propertyName): TrinaryLogic @@ -681,7 +681,7 @@ public function getUnresolvedStaticPropertyPrototype(string $propertyName, Class return $propertyPrototypes[0]; } - return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function canCallMethods(): TrinaryLogic diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index e129e52f73f..ddd98803841 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -214,7 +214,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember return $properties[0]; } - return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $properties); + return new UnionTypeUnresolvedPropertyPrototypeReflection($properties); } } } @@ -320,7 +320,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla return $properties[0]; } - return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $properties); + return new UnionTypeUnresolvedPropertyPrototypeReflection($properties); } } } diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index ae1f5572eb2..a29b089a0b6 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -521,7 +521,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember return $propertyPrototypes[0]; } - return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasInstanceProperty(string $propertyName): TrinaryLogic @@ -554,7 +554,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla return $propertyPrototypes[0]; } - return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasStaticProperty(string $propertyName): TrinaryLogic @@ -587,7 +587,7 @@ public function getUnresolvedStaticPropertyPrototype(string $propertyName, Class return $propertyPrototypes[0]; } - return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); + return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function canCallMethods(): TrinaryLogic From 5636bb6dfe3149b271d5a531d232aad28bc12c6e Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Tue, 5 May 2026 08:41:55 +0000 Subject: [PATCH 3/4] Remove unused $universalObjectCratesClasses from ImpossibleCheckTypeHelper Co-Authored-By: Claude Opus 4.6 --- src/Rules/Comparison/ImpossibleCheckTypeHelper.php | 6 ------ .../TypeSpecifyingFunctionsDynamicReturnTypeExtension.php | 7 +------ .../Comparison/BooleanAndConstantConditionRuleTest.php | 1 - .../Comparison/BooleanNotConstantConditionRuleTest.php | 1 - .../Comparison/BooleanOrConstantConditionRuleTest.php | 1 - .../Comparison/DoWhileLoopConstantConditionRuleTest.php | 1 - .../Rules/Comparison/ElseIfConstantConditionRuleTest.php | 1 - .../Rules/Comparison/IfConstantConditionRuleTest.php | 1 - .../Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php | 2 -- .../ImpossibleCheckTypeGenericOverwriteRuleTest.php | 1 - .../ImpossibleCheckTypeMethodCallRuleEqualsTest.php | 1 - .../Comparison/ImpossibleCheckTypeMethodCallRuleTest.php | 1 - .../ImpossibleCheckTypeStaticMethodCallRuleTest.php | 1 - .../Comparison/LogicalXorConstantConditionRuleTest.php | 1 - tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php | 1 - .../TernaryOperatorConstantConditionRuleTest.php | 1 - .../Comparison/WhileLoopAlwaysFalseConditionRuleTest.php | 1 - .../Comparison/WhileLoopAlwaysTrueConditionRuleTest.php | 1 - 18 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index 127cae01cd9..25c70705792 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -44,15 +44,10 @@ final class ImpossibleCheckTypeHelper { - /** - * @param string[] $universalObjectCratesClasses - */ public function __construct( private ReflectionProvider $reflectionProvider, private TypeSpecifier $typeSpecifier, #[AutowiredParameter] - private array $universalObjectCratesClasses, - #[AutowiredParameter] private bool $treatPhpDocTypesAsCertain, ) { @@ -417,7 +412,6 @@ public function doNotTreatPhpDocTypesAsCertain(): self return new self( $this->reflectionProvider, $this->typeSpecifier, - $this->universalObjectCratesClasses, false, ); } diff --git a/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php b/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php index 8ed3c6b6056..fdc77b5e4a5 100644 --- a/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php +++ b/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php @@ -25,15 +25,10 @@ final class TypeSpecifyingFunctionsDynamicReturnTypeExtension implements Dynamic private ?ImpossibleCheckTypeHelper $helper = null; - /** - * @param string[] $universalObjectCratesClasses - */ public function __construct( private ReflectionProvider $reflectionProvider, #[AutowiredParameter] private bool $treatPhpDocTypesAsCertain, - #[AutowiredParameter] - private array $universalObjectCratesClasses, ) { } @@ -76,7 +71,7 @@ public function getTypeFromFunctionCall( private function getHelper(): ImpossibleCheckTypeHelper { - return $this->helper ??= new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, $this->treatPhpDocTypesAsCertain); + return $this->helper ??= new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->treatPhpDocTypesAsCertain); } } diff --git a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php index b332d01adb8..114c61812b2 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php @@ -23,7 +23,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php index 3cf3f2a8bbc..f86e67ef693 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php @@ -23,7 +23,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php index 75b53752284..e2d84d9e7a6 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php index 97b3d705baf..3bd0c71136a 100644 --- a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php @@ -18,7 +18,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->shouldTreatPhpDocTypesAsCertain(), ), $this->shouldTreatPhpDocTypesAsCertain(), diff --git a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php index 220b7e115c1..92f14d6dd33 100644 --- a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php index 22f9d9577c0..0861db6f447 100644 --- a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php @@ -21,7 +21,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 2c63aec4647..2e50b4c511c 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -6,7 +6,6 @@ use PHPStan\Testing\RuleTestCase; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresPhp; -use stdClass; use function array_filter; use function array_map; use function array_values; @@ -28,7 +27,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [stdClass::class], $this->treatPhpDocTypesAsCertain, ), new PossiblyImpureTipHelper(true), diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 0190415a989..bb98ecf94bb 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -17,7 +17,6 @@ public function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], true, ), new PossiblyImpureTipHelper(true), diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php index 178b4148958..f48b76d5389 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php @@ -17,7 +17,6 @@ public function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], true, ), new PossiblyImpureTipHelper(true), diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 532239185d6..8648a231d1b 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -23,7 +23,6 @@ public function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), new PossiblyImpureTipHelper(true), diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php index 9022834bf99..1f18b019e47 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php @@ -23,7 +23,6 @@ public function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), new PossiblyImpureTipHelper(true), diff --git a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php index 14b97daacaa..5ca7530b60a 100644 --- a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php @@ -18,7 +18,6 @@ protected function getRule(): TRule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->shouldTreatPhpDocTypesAsCertain(), ), $this->shouldTreatPhpDocTypesAsCertain(), diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index 26b415ce9a5..7ab3586dfec 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -21,7 +21,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php index 300484a89b7..4cf6c399ea7 100644 --- a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php @@ -20,7 +20,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php index e84fdb4d566..10c0fef19ad 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php @@ -18,7 +18,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->shouldTreatPhpDocTypesAsCertain(), ), $this->shouldTreatPhpDocTypesAsCertain(), diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php index 7cf64f83b88..f365fb0a9e5 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php @@ -19,7 +19,6 @@ protected function getRule(): Rule new ImpossibleCheckTypeHelper( self::createReflectionProvider(), $this->getTypeSpecifier(), - [], $this->shouldTreatPhpDocTypesAsCertain(), ), $this->shouldTreatPhpDocTypesAsCertain(), From da2bda27ca0be84da5d0ed44564ee64ba8196a1f Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Tue, 5 May 2026 09:17:52 +0000 Subject: [PATCH 4/4] Remove stray blank line from baseline file Co-Authored-By: Claude Opus 4.6 --- phpstan-baseline.neon | 1 - 1 file changed, 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 74e554f9f27..ec7779bfbed 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -519,7 +519,6 @@ parameters: count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - - rawMessage: 'Doing instanceof PHPStan\Type\Constant\ConstantBooleanType is error-prone and deprecated. Use Type::isTrue() or Type::isFalse() instead.' identifier: phpstanApi.instanceofType