From f6db0aa3ce8d279eb1eae08121082a52cc4debbd Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 1 Jul 2026 13:46:22 +0200 Subject: [PATCH 1/3] [TypeDeclaration] Skip anonymous class in NarrowObjectReturnTypeRector --- .../skip_anonymous_class_this_return.php.inc | 27 +++++++++++++++++++ .../Source/Email.php | 9 +++++++ .../NarrowObjectReturnTypeRector.php | 8 ++++++ 3 files changed, 44 insertions(+) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc new file mode 100644 index 00000000000..d6f93feb14d --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc @@ -0,0 +1,27 @@ +id; + } + + public function setId(int $id): Email + { + $this->id = $id; + + return $this; + } + }; + } +} diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php new file mode 100644 index 00000000000..2a9eac4545b --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php @@ -0,0 +1,9 @@ +reflectionProvider->hasClass($className)) { + $returnedClassReflection = $this->reflectionProvider->getClass($className); + if ($returnedClassReflection->isAnonymous()) { + return null; + } + } + if ($returnedClass === null) { $returnedClass = $className; } elseif ($returnedClass !== $className) { From ef0bf7b6a59f6ec3552bd6e94a6435226e52794b Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 1 Jul 2026 14:11:19 +0200 Subject: [PATCH 2/3] [Privatization] Narrow ConstantArrayType filter to satisfy PHPStan native type check --- ...rrayTypeLeastCommonDenominatorResolver.php | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php b/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php index 184554d2467..ecda18e58de 100644 --- a/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php +++ b/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php @@ -10,7 +10,6 @@ use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; -use PHPStan\Type\VerbosityLevel; /** * Made with GPT-5 @@ -37,45 +36,6 @@ public function sharedArrayStructure(Type ...$types): Type } } - // If all are ConstantArrayType and have the *same* ordered key list -> preserve shape. - $allConstantArrayTypes = array_reduce($types, fn ($c, $t): bool => $c && $t instanceof ConstantArrayType, true); - if ($allConstantArrayTypes) { - /** @var ConstantArrayType[] $consts */ - $consts = $types; - - // Compare key sets (by stringified key types) - $firstKeys = array_map( - fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()), - $consts[0]->getKeyTypes() - ); - foreach ($consts as $c) { - $keys = array_map( - fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()), - $c->getKeyTypes() - ); - if ($keys !== $firstKeys) { - $allConstantArrayTypes = false; - break; - } - } - - if ($allConstantArrayTypes) { - $resultKeyTypes = $consts[0]->getKeyTypes(); - $valueColumns = []; - foreach ($consts as $const) { - $valueColumns[] = $const->getValueTypes(); - } - - $resultValueTypes = []; - foreach (array_keys($resultKeyTypes) as $i) { - $col = array_column($valueColumns, $i); - $resultValueTypes[] = $this->sharedArrayStructure(...$col); - } - - return new ConstantArrayType($resultKeyTypes, $resultValueTypes); - } - } - // Generic ArrayType path: reconcile key type + recurse into item types /** @var ArrayType[] $types */ /** @var ArrayType[] $arrayTypes */ From 1c7f5cda5c856e6201c4f0002a09cfca2093749a Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 1 Jul 2026 12:26:14 +0000 Subject: [PATCH 3/3] [ci-review] Rector Rectify --- .../TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php b/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php index ecda18e58de..f5c05a53aa8 100644 --- a/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php +++ b/rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php @@ -5,7 +5,6 @@ namespace Rector\Privatization\TypeManipulator; use PHPStan\Type\ArrayType; -use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\Type;