diff --git a/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc b/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc new file mode 100644 index 00000000000..4172dfbc3ab --- /dev/null +++ b/rules-tests/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector/Fixture/generic.php.inc @@ -0,0 +1,41 @@ +value = $value; + } +} +?> +----- + diff --git a/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php b/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php index 654ca3e9eed..462f6551ed4 100644 --- a/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php +++ b/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.php @@ -12,6 +12,7 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Property; +use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use Rector\Core\PhpParser\Comparing\NodeComparator; @@ -186,12 +187,11 @@ private function hasConflictingParamType(Param $param, Type $propertyType): bool $isAllFullyQualifiedObjectType = true; if ($propertyType instanceof UnionType) { - foreach ($propertyType->getTypes() as $type) { - if (! $type instanceof FullyQualifiedObjectType) { - $isAllFullyQualifiedObjectType = false; - break; - } + if ($this->hasGenericTemplateType($propertyType)) { + return false; } + + $isAllFullyQualifiedObjectType = ! $this->hasNonFullyQualifiedObjectType($propertyType); } // different types, not a good to fit @@ -201,6 +201,28 @@ private function hasConflictingParamType(Param $param, Type $propertyType): bool ); } + private function hasNonFullyQualifiedObjectType(UnionType $unionType): bool + { + foreach ($unionType->getTypes() as $type) { + if (! $type instanceof FullyQualifiedObjectType) { + return true; + } + } + + return false; + } + + private function hasGenericTemplateType(UnionType $unionType): bool + { + foreach ($unionType->getTypes() as $type) { + if ($type instanceof TemplateType) { + return true; + } + } + + return false; + } + /** * @param int[] $firstParamAsVariable */ @@ -215,12 +237,12 @@ private function shouldSkipParam( return true; } - // @todo unknown type, not suitable? - $propertyType = $this->propertyTypeInferer->inferProperty($property); - if ($this->hasConflictingParamType($matchedParam, $propertyType)) { + if ($this->isParamUsedBeforeAssign($assignedVariable, $firstParamAsVariable)) { return true; } - return $this->isParamUsedBeforeAssign($assignedVariable, $firstParamAsVariable); + // @todo unknown type, not suitable? + $propertyType = $this->propertyTypeInferer->inferProperty($property); + return $this->hasConflictingParamType($matchedParam, $propertyType); } }