From 26b1fa8241b6c7d7e814519c7874a031bcc02519 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:28:24 +0700 Subject: [PATCH 1/7] [TypeDeclarationDocblocks] Skip mixed|mixed[] on ClassMethodArrayDocblockParamFromLocalCallsRector --- .../Fixture/skip_union_mixed_array.php.inc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector/Fixture/skip_union_mixed_array.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector/Fixture/skip_union_mixed_array.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector/Fixture/skip_union_mixed_array.php.inc new file mode 100644 index 00000000000..4218fc66e20 --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector/Fixture/skip_union_mixed_array.php.inc @@ -0,0 +1,15 @@ +exec($_SERVER['argv'] ?? []); + } + + private function exec(array $argv) + { + } +} \ No newline at end of file From 29678181a52015f12f947dbc4559cf59c1ef945f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:49:12 +0700 Subject: [PATCH 2/7] Fix --- .../NodeAnalyzer/CallTypesResolver.php | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 1dff26fafb2..d9afe329aaf 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -14,6 +14,7 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ArrayType; use PHPStan\Type\MixedType; +use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\ThisType; use PHPStan\Type\Type; @@ -223,13 +224,34 @@ private function isEmptyArray(Expr $expr): bool private function isArrayMixedMixedType(Type $type): bool { if (! $type instanceof ArrayType) { + if ($type instanceof UnionType) { + $type = $this->typeFactory->createMixedPassedOrUnionType($type->getTypes()); + + if ($type instanceof UnionType) { + $hasMixedType = false; + $hasMixedArrayType = false; + foreach ($type->getTypes() as $unionedType) { + if ($unionedType instanceof MixedType) { + $hasMixedType = true; + continue; + } + + if ($this->isArrayMixedMixedType($unionedType)) { + $hasMixedArrayType = true; + } + } + + return $hasMixedType && $hasMixedArrayType; + } + } + return false; } - if (! $type->getItemType() instanceof MixedType) { + if (! $type->getItemType() instanceof MixedType && ! $type->getItemType() instanceof NeverType) { return false; } - return $type->getKeyType() instanceof MixedType; + return $type->getKeyType() instanceof MixedType || $type->getKeyType() instanceof NeverType; } } From 90a08b697f19c6c6be5ca7c19167ba1c337631e6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:49:31 +0700 Subject: [PATCH 3/7] Fix --- rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index d9afe329aaf..3c78dff96a0 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -241,7 +241,9 @@ private function isArrayMixedMixedType(Type $type): bool } } - return $hasMixedType && $hasMixedArrayType; + if ($hasMixedType && $hasMixedArrayType) { + return true; + } } } From cb1f7d7f40868ebc2079877c2fff2cbb80e537f8 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:51:19 +0700 Subject: [PATCH 4/7] Fix --- rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 3c78dff96a0..4953217b460 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -228,9 +228,15 @@ private function isArrayMixedMixedType(Type $type): bool $type = $this->typeFactory->createMixedPassedOrUnionType($type->getTypes()); if ($type instanceof UnionType) { + $types = $type->getTypes(); + if (count($types) !== 2) { + return false; + } + $hasMixedType = false; $hasMixedArrayType = false; - foreach ($type->getTypes() as $unionedType) { + + foreach ($types as $unionedType) { if ($unionedType instanceof MixedType) { $hasMixedType = true; continue; From d76de928174f3d6834c31b2af5e8d5754c20f8b0 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:52:15 +0700 Subject: [PATCH 5/7] Fix --- rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 4953217b460..04e96dc8049 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -225,10 +225,10 @@ private function isArrayMixedMixedType(Type $type): bool { if (! $type instanceof ArrayType) { if ($type instanceof UnionType) { - $type = $this->typeFactory->createMixedPassedOrUnionType($type->getTypes()); + $types = $type->getTypes(); + $type = $this->typeFactory->createMixedPassedOrUnionType($types); if ($type instanceof UnionType) { - $types = $type->getTypes(); if (count($types) !== 2) { return false; } From c5c325fc12a06c6966c62e7c2ebdb8ccc9b25887 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 00:52:53 +0700 Subject: [PATCH 6/7] Fix --- rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 04e96dc8049..416803c34b7 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -226,9 +226,10 @@ private function isArrayMixedMixedType(Type $type): bool if (! $type instanceof ArrayType) { if ($type instanceof UnionType) { $types = $type->getTypes(); - $type = $this->typeFactory->createMixedPassedOrUnionType($types); + $checkedType = $this->typeFactory->createMixedPassedOrUnionType($types); - if ($type instanceof UnionType) { + if ($checkedType instanceof UnionType) { + $types = $checkedType->getTypes(); if (count($types) !== 2) { return false; } From 99e5f2cf0b91ed3e7dcf59f8729c55e7c4fca293 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Sep 2025 01:09:08 +0700 Subject: [PATCH 7/7] Fix --- .../NodeAnalyzer/CallTypesResolver.php | 44 +++++-------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 416803c34b7..68ae54b0fcb 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -14,7 +14,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ArrayType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\ThisType; use PHPStan\Type\Type; @@ -136,6 +135,15 @@ private function unionToSingleType(array $staticTypesByArgumentPosition, bool $r if ($staticTypeByArgumentPosition[$position]->isNull()->yes()) { $staticTypeByArgumentPosition[$position] = new MixedType(); } + + if ($staticTypeByArgumentPosition[$position] instanceof UnionType) { + foreach ($staticTypeByArgumentPosition[$position]->getTypes() as $subType) { + if ($subType instanceof MixedType) { + $staticTypeByArgumentPosition[$position] = new MixedType(); + continue 2; + } + } + } } return $staticTypeByArgumentPosition; @@ -224,43 +232,13 @@ private function isEmptyArray(Expr $expr): bool private function isArrayMixedMixedType(Type $type): bool { if (! $type instanceof ArrayType) { - if ($type instanceof UnionType) { - $types = $type->getTypes(); - $checkedType = $this->typeFactory->createMixedPassedOrUnionType($types); - - if ($checkedType instanceof UnionType) { - $types = $checkedType->getTypes(); - if (count($types) !== 2) { - return false; - } - - $hasMixedType = false; - $hasMixedArrayType = false; - - foreach ($types as $unionedType) { - if ($unionedType instanceof MixedType) { - $hasMixedType = true; - continue; - } - - if ($this->isArrayMixedMixedType($unionedType)) { - $hasMixedArrayType = true; - } - } - - if ($hasMixedType && $hasMixedArrayType) { - return true; - } - } - } - return false; } - if (! $type->getItemType() instanceof MixedType && ! $type->getItemType() instanceof NeverType) { + if (! $type->getItemType() instanceof MixedType) { return false; } - return $type->getKeyType() instanceof MixedType || $type->getKeyType() instanceof NeverType; + return $type->getKeyType() instanceof MixedType; } }