diff --git a/rules/TypeDeclaration/TypeInferer/AssignToPropertyTypeInferer.php b/rules/TypeDeclaration/TypeInferer/AssignToPropertyTypeInferer.php index 433fb122eee..d988bc275d9 100644 --- a/rules/TypeDeclaration/TypeInferer/AssignToPropertyTypeInferer.php +++ b/rules/TypeDeclaration/TypeInferer/AssignToPropertyTypeInferer.php @@ -120,10 +120,13 @@ private function resolveTypeWithVerifyDefaultValue(Property $property, array $as return null; } $inferredType = $this->typeFactory->createMixedPassedOrUnionType($assignedExprTypes); + // to compare with default value, constant type must not be kept + // eg, use more general bool over false or true if ($this->shouldSkipWithDifferentDefaultValueType($defaultPropertyValue, $inferredType)) { return null; } - return $inferredType; + // returns with constant as final result + return $this->typeFactory->createMixedPassedOrUnionType($assignedExprTypes, \true); } private function shouldSkipWithDifferentDefaultValueType(?Expr $expr, Type $inferredType) : bool { diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index c9e6667183e..5e70ac77584 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '1c9f2321754a7592a17f21b817c7c83548050e76'; + public const PACKAGE_VERSION = '457927353525b5f87771493eaa7f79523383b071'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-12-12 05:31:26'; + public const RELEASE_DATE = '2024-12-12 07:46:01'; /** * @var int */ diff --git a/src/NodeAnalyzer/ExprAnalyzer.php b/src/NodeAnalyzer/ExprAnalyzer.php index 25466b997a2..74a199fbb21 100644 --- a/src/NodeAnalyzer/ExprAnalyzer.php +++ b/src/NodeAnalyzer/ExprAnalyzer.php @@ -36,10 +36,10 @@ public function isNonTypedFromParam(Expr $expr) : bool return \true; } $nativeType = $scope->getNativeType($expr); - if ($nativeType instanceof MixedType && !$nativeType->isExplicitMixed()) { + $type = $scope->getType($expr); + if ($nativeType instanceof MixedType && !$nativeType->isExplicitMixed() || $nativeType instanceof MixedType && !$type instanceof MixedType) { return \true; } - $type = $scope->getType($expr); if ($nativeType instanceof ObjectWithoutClassType && !$type instanceof ObjectWithoutClassType) { return \true; } diff --git a/src/NodeTypeResolver/NodeTypeResolver.php b/src/NodeTypeResolver/NodeTypeResolver.php index 4a2e8916047..dcf73927894 100644 --- a/src/NodeTypeResolver/NodeTypeResolver.php +++ b/src/NodeTypeResolver/NodeTypeResolver.php @@ -8,11 +8,13 @@ use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\BinaryOp\Coalesce; use PhpParser\Node\Expr\ClassConstFetch; +use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\NullsafeMethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Ternary; +use PhpParser\Node\Name; use PhpParser\Node\NullableType; use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\ClassConst; @@ -22,6 +24,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Broker\ClassAutoloadingException; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\Native\NativeFunctionReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantArrayType; @@ -472,6 +475,19 @@ private function resolveNativeTypeWithBuiltinMethodCallFallback(Expr $expr, Scop return $scope->getType($expr); } } + if ($expr instanceof FuncCall) { + if (!$expr->name instanceof Name) { + return $scope->getNativeType($expr); + } + if (!$this->reflectionProvider->hasFunction($expr->name, $scope)) { + return $scope->getNativeType($expr); + } + $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); + if (!$functionReflection instanceof NativeFunctionReflection) { + return $scope->getNativeType($expr); + } + return $scope->getType($expr); + } return $scope->getNativeType($expr); } }