diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ArrayParamTypeByMethodCallTypeRector/Fixture/skip_trait.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ArrayParamTypeByMethodCallTypeRector/Fixture/skip_trait.php.inc new file mode 100644 index 00000000000..6c66c3b3c95 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ArrayParamTypeByMethodCallTypeRector/Fixture/skip_trait.php.inc @@ -0,0 +1,15 @@ +use($value); + } + + private function use(array $value): void + { + } +} diff --git a/rules/TypeDeclaration/Rector/ClassMethod/AbstractParamTypeByMethodCallTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/AbstractParamTypeByMethodCallTypeRector.php index bfae44424e3..ac46f5b8946 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/AbstractParamTypeByMethodCallTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/AbstractParamTypeByMethodCallTypeRector.php @@ -13,6 +13,7 @@ use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; +use PHPStan\Analyser\Scope; use PHPStan\Type\Type; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory; @@ -99,6 +100,12 @@ abstract protected function isMatchingParamType(Type $type): bool; private function shouldSkipClassMethod(ClassMethod $classMethod): bool { + // trait method can be used in a class that requires a contract type, adding a param type would break it + $scope = $classMethod->getAttribute(AttributeKey::SCOPE); + if ($scope instanceof Scope && $scope->isInTrait()) { + return true; + } + // user-guarded class: adding a param type here would break its child classes if ($this->parentClassMethodTypeOverrideGuard->isTypeGuardedClass($classMethod)) { return true;