diff --git a/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php b/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php index 88c9dd86fc..c14d609440 100644 --- a/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php @@ -10,10 +10,12 @@ use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Reflection\FunctionReflection; +use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ErrorType; use PHPStan\Type\FunctionTypeSpecifyingExtension; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; +use PHPStan\Type\ObjectWithoutClassType; use PHPStan\Type\TypeCombinator; use stdClass; use function count; @@ -41,7 +43,15 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $constantStrings = $castType->getConstantStrings(); if (count($constantStrings) < 1) { - return new SpecifiedTypes(); + $constantStrings = [ + new ConstantStringType('bool'), + new ConstantStringType('int'), + new ConstantStringType('float'), + new ConstantStringType('string'), + new ConstantStringType('array'), + new ConstantStringType('object'), + new ConstantStringType('null'), + ]; } $types = []; @@ -67,7 +77,17 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $types[] = $valueType->toArray(); break; case 'object': - $types[] = new ObjectType(stdClass::class); + $isObject = $valueType->isObject(); + if ($isObject->yes()) { + $types[] = $valueType; + } elseif ($isObject->no()) { + $types[] = new ObjectType(stdClass::class); + } else { + $types[] = TypeCombinator::union( + TypeCombinator::intersect($valueType, new ObjectWithoutClassType()), + new ObjectType(stdClass::class), + ); + } break; case 'null': $types[] = new NullType(); diff --git a/tests/PHPStan/Analyser/nsrt/bug-3250.php b/tests/PHPStan/Analyser/nsrt/bug-3250.php new file mode 100644 index 0000000000..ec52c27fe9 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-3250.php @@ -0,0 +1,61 @@ +