Skip to content

Commit

Permalink
Fix issues about assigning typed properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 21, 2025
1 parent b6b8ebd commit bed30a7
Show file tree
Hide file tree
Showing 37 changed files with 235 additions and 17 deletions.
22 changes: 6 additions & 16 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5556,15 +5556,10 @@ static function (): void {
$assignedExprType = $scope->getType($assignedExpr);
$nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope);
if ($propertyReflection->canChangeTypeAfterAssignment()) {
if ($propertyReflection->hasNativeType()) {
if ($propertyReflection->hasNativeType() && $scope->isDeclareStrictTypes()) {
$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);
}

$scope = $scope->assignExpression($var, TypeCombinator::intersect($assignedExprType->toCoercedArgumentType(true), $propertyNativeType), TypeCombinator::intersect($scope->getNativeType($assignedExpr)->toCoercedArgumentType(true), $propertyNativeType));
} else {
$scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr));
}
Expand Down Expand Up @@ -5632,15 +5627,10 @@ static function (): void {
$assignedExprType = $scope->getType($assignedExpr);
$nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope);
if ($propertyReflection !== null && $propertyReflection->canChangeTypeAfterAssignment()) {
if ($propertyReflection->hasNativeType()) {
if ($propertyReflection->hasNativeType() && $scope->isDeclareStrictTypes()) {
$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);
}

$scope = $scope->assignExpression($var, TypeCombinator::intersect($assignedExprType->toCoercedArgumentType(true), $propertyNativeType), TypeCombinator::intersect($scope->getNativeType($assignedExpr)->toCoercedArgumentType(true), $propertyNativeType));
} else {
$scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr));
}
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryArrayListType.php
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function traverse(callable $cb): Type
{
return $this;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLowercaseStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonFalsyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ public function toArrayKey(): Type
return new IntegerType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryUppercaseStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function getEnumCases(): array
{
return [];
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetValueType.php
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function getEnumCases(): array
{
return [];
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function traverse(callable $cb): Type
{
return $this;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/OversizedArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function traverse(callable $cb): Type
{
return $this;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/BooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ public function toArrayKey(): Type
return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]);
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
6 changes: 6 additions & 0 deletions src/Type/CallableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type;

use Closure;
use PHPStan\Analyser\OutOfClassScope;
use PHPStan\Php\PhpVersion;
use PHPStan\PhpDoc\Tag\TemplateTag;
Expand Down Expand Up @@ -321,6 +322,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return TypeCombinator::union($this, new StringType(), new ArrayType(new MixedType(true), new MixedType(true)), new ObjectType(Closure::class));
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ClosureType.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return TypeCombinator::union($this, new CallableType());
}

public function getTemplateTypeMap(): TemplateTypeMap
{
return $this->templateTypeMap;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Constant/ConstantBooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ public function toArrayKey(): Type
return new ConstantIntegerType((int) $this->value);
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isTrue(): TrinaryLogic
{
return TrinaryLogic::createFromBoolean($this->value === true);
Expand Down
5 changes: 5 additions & 0 deletions src/Type/FloatType.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public function toArrayKey(): Type
return new IntegerType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Generic/TemplateTypeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
{
if (
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IntegerType.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return TypeCombinator::union($this, $this->toFloat());
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,11 @@ public function toArrayKey(): Type
return $this->intersectTypes(static fn (Type $type): Type => $type->toArrayKey());
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this->intersectTypes(static fn (Type $type): Type => $type->toCoercedArgumentType($strictTypes));
}

public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
{
$types = TemplateTypeMap::createEmpty();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IterableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return TypeCombinator::union($this, new ArrayType(new MixedType(true), new MixedType(true)), new ObjectType(Traversable::class));
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/MixedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,11 @@ public function toArrayKey(): Type
return new BenevolentUnionType([new IntegerType(), new StringType()]);
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isIterable(): TrinaryLogic
{
if ($this->subtractedType !== null) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NeverType.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function traverse(callable $cb): Type
{
return $this;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NonexistentParentClassType.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return new ErrorType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NullType.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ public function toArrayKey(): Type
return new ConstantStringType('');
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,11 @@ public function toArrayKey(): Type
return $this->toString();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function toBoolean(): BooleanType
{
if ($this->isInstanceOf('SimpleXMLElement')->yes()) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ResourceType.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StaticType.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,11 @@ public function toArrayKey(): Type
return $this->getStaticObjectType()->toArrayKey();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this->getStaticObjectType()->toCoercedArgumentType($strictTypes);
}

public function toBoolean(): BooleanType
{
return $this->getStaticObjectType()->toBoolean();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StrictMixedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
{
return TemplateTypeMap::createEmpty();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ public function toArrayKey(): Type
return $this;
}

public function toCoercedArgumentType(bool $strictTypes): Type
{
return $this;
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
Loading

0 comments on commit bed30a7

Please sign in to comment.