From bf923adb994d7b1f18954f2bb8ab3f855485b331 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 19 Jan 2025 14:54:15 +0100 Subject: [PATCH] Revert "Overwrite property expression type only if it's subtype of the native type" This reverts commit eb0e0bcfe2e4947d06c5eb680f5cf568a688ff4a. --- src/Analyser/MutatingScope.php | 15 ++- src/Analyser/NodeScopeResolver.php | 26 +---- .../AnnotationPropertyReflection.php | 21 ---- .../Dummy/ChangedTypePropertyReflection.php | 22 +---- .../Dummy/DummyPropertyReflection.php | 20 ---- src/Reflection/ExtendedPropertyReflection.php | 9 -- src/Reflection/Php/EnumPropertyReflection.php | 21 ---- .../Php/SimpleXMLElementProperty.php | 21 ---- .../Php/UniversalObjectCrateProperty.php | 21 ---- src/Reflection/ResolvedPropertyReflection.php | 20 ---- ...kUnresolvedPropertyPrototypeReflection.php | 4 +- ...eUnresolvedPropertyPrototypeReflection.php | 4 +- .../IntersectionTypePropertyReflection.php | 20 ---- .../Type/UnionTypePropertyReflection.php | 20 ---- .../WrappedExtendedPropertyReflection.php | 21 ---- .../Properties/FoundPropertyReflection.php | 30 ++---- src/Type/ObjectShapePropertyReflection.php | 20 ---- tests/PHPStan/Analyser/nsrt/bug-12393.php | 99 ------------------- 18 files changed, 21 insertions(+), 393 deletions(-) delete mode 100644 tests/PHPStan/Analyser/nsrt/bug-12393.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 3bd6db7556..297697ee78 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2119,12 +2119,10 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu if ($propertyReflection === null) { return new ErrorType(); } - - if (!$propertyReflection->hasNativeType()) { - return new MixedType(); - } - $nativeType = $propertyReflection->getNativeType(); + if ($nativeType === null) { + return new ErrorType(); + } return $this->getNullsafeShortCircuitingType($node->var, $nativeType); } @@ -2169,11 +2167,10 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu if ($propertyReflection === null) { return new ErrorType(); } - if (!$propertyReflection->hasNativeType()) { - return new MixedType(); - } - $nativeType = $propertyReflection->getNativeType(); + if ($nativeType === null) { + return new ErrorType(); + } if ($node->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($node->class, $nativeType); diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index e91ca6748e..58b6f34df5 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -5556,18 +5556,7 @@ static function (): void { $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); if ($propertyReflection->canChangeTypeAfterAssignment()) { - if ($propertyReflection->hasNativeType()) { - $propertyNativeType = $propertyReflection->getNativeType(); - if ($propertyNativeType->isSuperTypeOf($assignedExprType)->yes()) { - $assignedExprNativeType = $scope->getNativeType($assignedExpr); - if (!$propertyNativeType->isSuperTypeOf($assignedExprNativeType)->yes()) { - $assignedExprNativeType = $propertyNativeType; - } - $scope = $scope->assignExpression($var, $assignedExprType, $assignedExprNativeType); - } - } else { - $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); - } + $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } $declaringClass = $propertyReflection->getDeclaringClass(); if ($declaringClass->hasNativeProperty($propertyName)) { @@ -5632,18 +5621,7 @@ static function (): void { $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); if ($propertyReflection !== null && $propertyReflection->canChangeTypeAfterAssignment()) { - if ($propertyReflection->hasNativeType()) { - $propertyNativeType = $propertyReflection->getNativeType(); - if ($propertyNativeType->isSuperTypeOf($assignedExprType)->yes()) { - $assignedExprNativeType = $scope->getNativeType($assignedExpr); - if (!$propertyNativeType->isSuperTypeOf($assignedExprNativeType)->yes()) { - $assignedExprNativeType = $propertyNativeType; - } - $scope = $scope->assignExpression($var, $assignedExprType, $assignedExprNativeType); - } - } else { - $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); - } + $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } else { // fallback diff --git a/src/Reflection/Annotations/AnnotationPropertyReflection.php b/src/Reflection/Annotations/AnnotationPropertyReflection.php index cc1994bc9a..9188ef7721 100644 --- a/src/Reflection/Annotations/AnnotationPropertyReflection.php +++ b/src/Reflection/Annotations/AnnotationPropertyReflection.php @@ -7,7 +7,6 @@ use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\MixedType; use PHPStan\Type\Type; final class AnnotationPropertyReflection implements ExtendedPropertyReflection @@ -43,26 +42,6 @@ public function isPublic(): bool return true; } - public function hasPhpDocType(): bool - { - return true; - } - - public function getPhpDocType(): Type - { - return $this->readableType; - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->readableType; diff --git a/src/Reflection/Dummy/ChangedTypePropertyReflection.php b/src/Reflection/Dummy/ChangedTypePropertyReflection.php index f235b2e6e3..07dc20ce68 100644 --- a/src/Reflection/Dummy/ChangedTypePropertyReflection.php +++ b/src/Reflection/Dummy/ChangedTypePropertyReflection.php @@ -12,7 +12,7 @@ final class ChangedTypePropertyReflection implements WrapperPropertyReflection { - public function __construct(private ClassReflection $declaringClass, private ExtendedPropertyReflection $reflection, private Type $readableType, private Type $writableType, private Type $phpDocType, private Type $nativeType) + public function __construct(private ClassReflection $declaringClass, private ExtendedPropertyReflection $reflection, private Type $readableType, private Type $writableType) { } @@ -41,26 +41,6 @@ public function getDocComment(): ?string return $this->reflection->getDocComment(); } - public function hasPhpDocType(): bool - { - return $this->reflection->hasPhpDocType(); - } - - public function getPhpDocType(): Type - { - return $this->phpDocType; - } - - public function hasNativeType(): bool - { - return $this->reflection->hasNativeType(); - } - - public function getNativeType(): Type - { - return $this->nativeType; - } - public function getReadableType(): Type { return $this->readableType; diff --git a/src/Reflection/Dummy/DummyPropertyReflection.php b/src/Reflection/Dummy/DummyPropertyReflection.php index c2c6d4c768..40a48911e8 100644 --- a/src/Reflection/Dummy/DummyPropertyReflection.php +++ b/src/Reflection/Dummy/DummyPropertyReflection.php @@ -37,26 +37,6 @@ public function isPublic(): bool return true; } - public function hasPhpDocType(): bool - { - return false; - } - - public function getPhpDocType(): Type - { - return new MixedType(); - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return new MixedType(); diff --git a/src/Reflection/ExtendedPropertyReflection.php b/src/Reflection/ExtendedPropertyReflection.php index 63b6246dd3..c4a55163bb 100644 --- a/src/Reflection/ExtendedPropertyReflection.php +++ b/src/Reflection/ExtendedPropertyReflection.php @@ -3,7 +3,6 @@ namespace PHPStan\Reflection; use PHPStan\TrinaryLogic; -use PHPStan\Type\Type; /** * The purpose of this interface is to be able to @@ -26,14 +25,6 @@ interface ExtendedPropertyReflection extends PropertyReflection public const HOOK_SET = 'set'; - public function hasPhpDocType(): bool; - - public function getPhpDocType(): Type; - - public function hasNativeType(): bool; - - public function getNativeType(): Type; - public function isAbstract(): TrinaryLogic; public function isFinal(): TrinaryLogic; diff --git a/src/Reflection/Php/EnumPropertyReflection.php b/src/Reflection/Php/EnumPropertyReflection.php index a74bb419ff..8a9a4eed28 100644 --- a/src/Reflection/Php/EnumPropertyReflection.php +++ b/src/Reflection/Php/EnumPropertyReflection.php @@ -7,7 +7,6 @@ use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\MixedType; use PHPStan\Type\Type; final class EnumPropertyReflection implements ExtendedPropertyReflection @@ -42,26 +41,6 @@ public function getDocComment(): ?string return null; } - public function hasPhpDocType(): bool - { - return false; - } - - public function getPhpDocType(): Type - { - return new MixedType(); - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->type; diff --git a/src/Reflection/Php/SimpleXMLElementProperty.php b/src/Reflection/Php/SimpleXMLElementProperty.php index d354ae5fe2..a8cfff2cb3 100644 --- a/src/Reflection/Php/SimpleXMLElementProperty.php +++ b/src/Reflection/Php/SimpleXMLElementProperty.php @@ -10,7 +10,6 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\FloatType; use PHPStan\Type\IntegerType; -use PHPStan\Type\MixedType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -45,26 +44,6 @@ public function isPublic(): bool return true; } - public function hasPhpDocType(): bool - { - return false; - } - - public function getPhpDocType(): Type - { - return new MixedType(); - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->type; diff --git a/src/Reflection/Php/UniversalObjectCrateProperty.php b/src/Reflection/Php/UniversalObjectCrateProperty.php index 0a2f8faf35..3382a49344 100644 --- a/src/Reflection/Php/UniversalObjectCrateProperty.php +++ b/src/Reflection/Php/UniversalObjectCrateProperty.php @@ -7,7 +7,6 @@ use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\MixedType; use PHPStan\Type\Type; final class UniversalObjectCrateProperty implements ExtendedPropertyReflection @@ -41,26 +40,6 @@ public function isPublic(): bool return true; } - public function hasPhpDocType(): bool - { - return false; - } - - public function getPhpDocType(): Type - { - return new MixedType(); - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->readableType; diff --git a/src/Reflection/ResolvedPropertyReflection.php b/src/Reflection/ResolvedPropertyReflection.php index e964d99b5e..d5ffc248c6 100644 --- a/src/Reflection/ResolvedPropertyReflection.php +++ b/src/Reflection/ResolvedPropertyReflection.php @@ -59,26 +59,6 @@ public function isPublic(): bool return $this->reflection->isPublic(); } - public function hasPhpDocType(): bool - { - return $this->reflection->hasPhpDocType(); - } - - public function getPhpDocType(): Type - { - return $this->reflection->getPhpDocType(); - } - - public function hasNativeType(): bool - { - return $this->reflection->hasNativeType(); - } - - public function getNativeType(): Type - { - return $this->reflection->getNativeType(); - } - public function getReadableType(): Type { $type = $this->readableType; diff --git a/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php b/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php index 06069f8410..151945e921 100644 --- a/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php +++ b/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php @@ -79,10 +79,8 @@ private function transformPropertyWithStaticType(ClassReflection $declaringClass { $readableType = $this->transformStaticType($property->getReadableType()); $writableType = $this->transformStaticType($property->getWritableType()); - $phpDocType = $this->transformStaticType($property->getPhpDocType()); - $nativeType = $this->transformStaticType($property->getNativeType()); - return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType, $phpDocType, $nativeType); + return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType); } private function transformStaticType(Type $type): Type diff --git a/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php b/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php index 18beaf3f8e..4b843829ad 100644 --- a/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php +++ b/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php @@ -74,10 +74,8 @@ private function transformPropertyWithStaticType(ClassReflection $declaringClass { $readableType = $this->transformStaticType($property->getReadableType()); $writableType = $this->transformStaticType($property->getWritableType()); - $phpDocType = $this->transformStaticType($property->getPhpDocType()); - $nativeType = $this->transformStaticType($property->getNativeType()); - return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType, $phpDocType, $nativeType); + return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType); } private function transformStaticType(Type $type): Type diff --git a/src/Reflection/Type/IntersectionTypePropertyReflection.php b/src/Reflection/Type/IntersectionTypePropertyReflection.php index 9976bab57d..b2d1551e5c 100644 --- a/src/Reflection/Type/IntersectionTypePropertyReflection.php +++ b/src/Reflection/Type/IntersectionTypePropertyReflection.php @@ -80,26 +80,6 @@ public function getDocComment(): ?string return null; } - public function hasPhpDocType(): bool - { - return $this->computeResult(static fn (ExtendedPropertyReflection $property) => $property->hasPhpDocType()); - } - - public function getPhpDocType(): Type - { - return TypeCombinator::intersect(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getPhpDocType(), $this->properties)); - } - - public function hasNativeType(): bool - { - return $this->computeResult(static fn (ExtendedPropertyReflection $property) => $property->hasNativeType()); - } - - public function getNativeType(): Type - { - return TypeCombinator::intersect(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getNativeType(), $this->properties)); - } - public function getReadableType(): Type { return TypeCombinator::intersect(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getReadableType(), $this->properties)); diff --git a/src/Reflection/Type/UnionTypePropertyReflection.php b/src/Reflection/Type/UnionTypePropertyReflection.php index 24e2e91156..bc3c4f4411 100644 --- a/src/Reflection/Type/UnionTypePropertyReflection.php +++ b/src/Reflection/Type/UnionTypePropertyReflection.php @@ -80,26 +80,6 @@ public function getDocComment(): ?string return null; } - public function hasPhpDocType(): bool - { - return $this->computeResult(static fn (ExtendedPropertyReflection $property) => $property->hasPhpDocType()); - } - - public function getPhpDocType(): Type - { - return TypeCombinator::union(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getPhpDocType(), $this->properties)); - } - - public function hasNativeType(): bool - { - return $this->computeResult(static fn (ExtendedPropertyReflection $property) => $property->hasNativeType()); - } - - public function getNativeType(): Type - { - return TypeCombinator::union(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getNativeType(), $this->properties)); - } - public function getReadableType(): Type { return TypeCombinator::union(...array_map(static fn (ExtendedPropertyReflection $property): Type => $property->getReadableType(), $this->properties)); diff --git a/src/Reflection/WrappedExtendedPropertyReflection.php b/src/Reflection/WrappedExtendedPropertyReflection.php index fe64beb0f0..52e1571309 100644 --- a/src/Reflection/WrappedExtendedPropertyReflection.php +++ b/src/Reflection/WrappedExtendedPropertyReflection.php @@ -4,7 +4,6 @@ use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\MixedType; use PHPStan\Type\Type; final class WrappedExtendedPropertyReflection implements ExtendedPropertyReflection @@ -39,26 +38,6 @@ public function getDocComment(): ?string return $this->property->getDocComment(); } - public function hasPhpDocType(): bool - { - return false; - } - - public function getPhpDocType(): Type - { - return new MixedType(); - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->property->getReadableType(); diff --git a/src/Rules/Properties/FoundPropertyReflection.php b/src/Rules/Properties/FoundPropertyReflection.php index 19e77db7e0..36a286a4a0 100644 --- a/src/Rules/Properties/FoundPropertyReflection.php +++ b/src/Rules/Properties/FoundPropertyReflection.php @@ -59,26 +59,6 @@ public function getDocComment(): ?string return $this->originalPropertyReflection->getDocComment(); } - public function hasPhpDocType(): bool - { - return $this->originalPropertyReflection->hasPhpDocType(); - } - - public function getPhpDocType(): Type - { - return $this->originalPropertyReflection->getPhpDocType(); - } - - public function hasNativeType(): bool - { - return $this->originalPropertyReflection->hasNativeType(); - } - - public function getNativeType(): Type - { - return $this->originalPropertyReflection->getNativeType(); - } - public function getReadableType(): Type { return $this->readableType; @@ -124,6 +104,16 @@ public function isNative(): bool return $this->getNativeReflection() !== null; } + public function getNativeType(): ?Type + { + $reflection = $this->getNativeReflection(); + if ($reflection === null) { + return null; + } + + return $reflection->getNativeType(); + } + public function getNativeReflection(): ?PhpPropertyReflection { $reflection = $this->originalPropertyReflection; diff --git a/src/Type/ObjectShapePropertyReflection.php b/src/Type/ObjectShapePropertyReflection.php index d5fb99f546..37a98fa9ba 100644 --- a/src/Type/ObjectShapePropertyReflection.php +++ b/src/Type/ObjectShapePropertyReflection.php @@ -44,26 +44,6 @@ public function getDocComment(): ?string return null; } - public function hasPhpDocType(): bool - { - return true; - } - - public function getPhpDocType(): Type - { - return $this->type; - } - - public function hasNativeType(): bool - { - return false; - } - - public function getNativeType(): Type - { - return new MixedType(); - } - public function getReadableType(): Type { return $this->type; diff --git a/tests/PHPStan/Analyser/nsrt/bug-12393.php b/tests/PHPStan/Analyser/nsrt/bug-12393.php deleted file mode 100644 index 5410dc2150..0000000000 --- a/tests/PHPStan/Analyser/nsrt/bug-12393.php +++ /dev/null @@ -1,99 +0,0 @@ -name = $plugin["name"]; - assertType('string', $this->name); - } - - /** - * @param mixed[] $plugin - */ - public function doFoo(array $plugin){ - $this->untypedName = $plugin["name"]; - assertType('mixed', $this->untypedName); - } - - public function doBar(int $i){ - $this->float = $i; - assertType('float', $this->float); - } - - public function doBaz(int $i){ - $this->untypedFloat = $i; - assertType('int', $this->untypedFloat); - } - - public function doLorem(): void - { - $this->a = ['a' => 1]; - assertType('array{a: 1}', $this->a); - } -} - -class HelloWorldStatic -{ - private static string $name; - - /** @var string */ - private static $untypedName; - - private static float $float; - - /** @var float */ - private static $untypedFloat; - - private static array $a; - - /** - * @param mixed[] $plugin - */ - public function __construct(array $plugin){ - self::$name = $plugin["name"]; - assertType('string', self::$name); - } - - /** - * @param mixed[] $plugin - */ - public function doFoo(array $plugin){ - self::$untypedName = $plugin["name"]; - assertType('mixed', self::$untypedName); - } - - public function doBar(int $i){ - self::$float = $i; - assertType('float', self::$float); - } - - public function doBaz(int $i){ - self::$untypedFloat = $i; - assertType('int', self::$untypedFloat); - } - - public function doLorem(): void - { - self::$a = ['a' => 1]; - assertType('array{a: 1}', self::$a); - } -}