Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegate most of TypeCombinator::remove() to Type::tryRemove() #994

Merged
merged 1 commit into from Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Expand Up @@ -17,6 +17,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
Expand All @@ -30,6 +31,7 @@ class AccessoryLiteralStringType implements CompoundType, AccessoryType
use NonIterableTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonGenericTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Expand Up @@ -15,6 +15,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -30,6 +31,7 @@ class AccessoryNonEmptyStringType implements CompoundType, AccessoryType
use TruthyBooleanTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonGenericTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Expand Up @@ -15,6 +15,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -30,6 +31,7 @@ class AccessoryNumericStringType implements CompoundType, AccessoryType
use UndecidedBooleanTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonGenericTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasMethodType.php
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Type\CompoundType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\ObjectTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -26,6 +27,7 @@ class HasMethodType implements AccessoryType, CompoundType
use ObjectTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct(private string $methodName)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -28,6 +29,7 @@ class HasOffsetType implements CompoundType, AccessoryType
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct(private Type $offsetType)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasPropertyType.php
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Type\CompoundType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\ObjectTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -21,6 +22,7 @@ class HasPropertyType implements AccessoryType, CompoundType
use ObjectTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct(private string $propertyName)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
Expand All @@ -26,6 +27,7 @@ class NonEmptyArrayType implements CompoundType, AccessoryType
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down
18 changes: 18 additions & 0 deletions src/Type/ArrayType.php
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Reflection\TrivialParametersAcceptor;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\HasOffsetType;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantFloatType;
Expand Down Expand Up @@ -420,6 +421,23 @@ public function traverse(callable $cb): Type
return $this;
}

public function tryRemove(Type $typeToRemove): ?Type
{
if ($typeToRemove instanceof ConstantArrayType && $typeToRemove->isIterableAtLeastOnce()->no()) {
return TypeCombinator::intersect($this, new NonEmptyArrayType());
}

if ($typeToRemove instanceof NonEmptyArrayType) {
return new ConstantArrayType([], []);
}

if ($this instanceof ConstantArrayType && $typeToRemove instanceof HasOffsetType) {
return $this->unsetOffset($typeToRemove->getOffsetType());
}

return null;
}

/**
* @param mixed[] $properties
*/
Expand Down
10 changes: 10 additions & 0 deletions src/Type/BooleanType.php
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Type;

use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Constant\ConstantFloatType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Constant\ConstantStringType;
Expand Down Expand Up @@ -75,6 +76,15 @@ public function toArray(): Type
);
}

public function tryRemove(Type $typeToRemove): ?Type
{
if ($typeToRemove instanceof ConstantBooleanType) {
return new ConstantBooleanType(!$typeToRemove->getValue());
}

return null;
}

/**
* @param mixed[] $properties
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Type/CallableType.php
Expand Up @@ -16,6 +16,7 @@
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use function array_map;
Expand All @@ -32,6 +33,7 @@ class CallableType implements CompoundType, ParametersAcceptor
use MaybeOffsetAccessibleTypeTrait;
use TruthyBooleanTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @var array<int, ParameterReflection> */
private array $parameters;
Expand Down
2 changes: 2 additions & 0 deletions src/Type/ClosureType.php
Expand Up @@ -24,6 +24,7 @@
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
use function array_map;
use function array_merge;
Expand All @@ -37,6 +38,7 @@ class ClosureType implements TypeWithClassName, ParametersAcceptor
use NonGenericTypeTrait;
use UndecidedComparisonTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonRemoveableTypeTrait;

private ObjectType $objectType;

Expand Down
9 changes: 9 additions & 0 deletions src/Type/Enum/EnumCaseObjectType.php
Expand Up @@ -91,6 +91,15 @@ public function getSubtractedType(): ?Type
return null;
}

public function tryRemove(Type $typeToRemove): ?Type
{
if ($this->isSuperTypeOf($typeToRemove)->yes()) {
return $this->subtract($typeToRemove);
}

return null;
}

public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection
{
$classReflection = $this->getClassReflection();
Expand Down
2 changes: 2 additions & 0 deletions src/Type/FloatType.php
Expand Up @@ -11,6 +11,7 @@
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
use function get_class;
Expand All @@ -26,6 +27,7 @@ class FloatType implements Type
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down
3 changes: 3 additions & 0 deletions src/Type/Generic/TemplateTypeTrait.php
Expand Up @@ -5,6 +5,7 @@
use PHPStan\TrinaryLogic;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use PHPStan\Type\VerbosityLevel;
Expand All @@ -16,6 +17,8 @@
trait TemplateTypeTrait
{

use NonRemoveableTypeTrait;

private string $name;

private TemplateTypeScope $scope;
Expand Down
21 changes: 21 additions & 0 deletions src/Type/IntegerType.php
Expand Up @@ -76,4 +76,25 @@ public function toArray(): Type
);
}

public function tryRemove(Type $typeToRemove): ?Type
{
if ($typeToRemove instanceof IntegerRangeType || $typeToRemove instanceof ConstantIntegerType) {
if ($typeToRemove instanceof IntegerRangeType) {
$removeValueMin = $typeToRemove->getMin();
$removeValueMax = $typeToRemove->getMax();
} else {
$removeValueMin = $typeToRemove->getValue();
$removeValueMax = $typeToRemove->getValue();
}
$lowerPart = $removeValueMin !== null ? IntegerRangeType::fromInterval(null, $removeValueMin, -1) : null;
$upperPart = $removeValueMax !== null ? IntegerRangeType::fromInterval($removeValueMax, null, +1) : null;
if ($lowerPart !== null && $upperPart !== null) {
return new UnionType([$lowerPart, $upperPart]);
}
return $lowerPart ?? $upperPart ?? new NeverType();
}

return null;
}

}
3 changes: 3 additions & 0 deletions src/Type/IntersectionType.php
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use function array_map;
use function count;
use function implode;
Expand All @@ -34,6 +35,8 @@
class IntersectionType implements CompoundType
{

use NonRemoveableTypeTrait;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see this trait being used by a lot of types, I'm pretty sure we could actually make them support type-removing in some scenarios :) But we can leave it for later.


/** @var Type[] */
private array $types;

Expand Down
19 changes: 19 additions & 0 deletions src/Type/IterableType.php
Expand Up @@ -4,6 +4,7 @@

use PHPStan\TrinaryLogic;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\Generic\TemplateMixedType;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeMap;
Expand Down Expand Up @@ -278,6 +279,24 @@ public function traverse(callable $cb): Type
return $this;
}

public function tryRemove(Type $typeToRemove): ?Type
{
$arrayType = new ArrayType(new MixedType(), new MixedType());
if ($typeToRemove->isSuperTypeOf($arrayType)->yes()) {
return new GenericObjectType(Traversable::class, [
$this->getIterableKeyType(),
$this->getIterableValueType(),
]);
}

$traversableType = new ObjectType(Traversable::class);
if ($typeToRemove->isSuperTypeOf($traversableType)->yes()) {
return new ArrayType($this->getIterableKeyType(), $this->getIterableValueType());
}

return null;
}

/**
* @param mixed[] $properties
*/
Expand Down
9 changes: 9 additions & 0 deletions src/Type/MixedType.php
Expand Up @@ -420,6 +420,15 @@ public function isLiteralString(): TrinaryLogic
return TrinaryLogic::createMaybe();
}

public function tryRemove(Type $typeToRemove): ?Type
{
if ($this->isSuperTypeOf($typeToRemove)->yes()) {
return $this->subtract($typeToRemove);
}

return null;
}

/**
* @param mixed[] $properties
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Type/NeverType.php
Expand Up @@ -13,6 +13,7 @@
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;

Expand All @@ -23,6 +24,7 @@ class NeverType implements CompoundType
use UndecidedBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct(private bool $isExplicit = false)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/NonexistentParentClassType.php
Expand Up @@ -14,6 +14,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;

Expand All @@ -27,6 +28,7 @@ class NonexistentParentClassType implements Type
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonTypeTrait;
use NonRemoveableTypeTrait;

public function describe(VerbosityLevel $level): string
{
Expand Down
2 changes: 2 additions & 0 deletions src/Type/NullType.php
Expand Up @@ -13,6 +13,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;

/** @api */
class NullType implements ConstantScalarType
Expand All @@ -23,6 +24,7 @@ class NullType implements ConstantScalarType
use NonObjectTypeTrait;
use FalseyBooleanTypeTrait;
use NonGenericTypeTrait;
use NonRemoveableTypeTrait;

/** @api */
public function __construct()
Expand Down