Skip to content

Commit

Permalink
Fix unset() on intersection with hasOffset
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 20, 2022
1 parent 8fc2f23 commit b43c057
Show file tree
Hide file tree
Showing 28 changed files with 177 additions and 129 deletions.
27 changes: 6 additions & 21 deletions src/Analyser/MutatingScope.php
Expand Up @@ -3694,27 +3694,12 @@ public function unsetExpression(Expr $expr): self
$this->parentScope,
);
} elseif ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) {
$varType = $this->getType($expr->var);
$constantArrays = TypeUtils::getConstantArrays($varType);
if (count($constantArrays) > 0) {
$unsetArrays = [];
$dimType = $this->getType($expr->dim);
foreach ($constantArrays as $constantArray) {
$unsetArrays[] = $constantArray->unsetOffset($dimType);
}
return $this->specifyExpressionType(
$expr->var,
TypeCombinator::union(...$unsetArrays),
);
}

$arrays = TypeUtils::getArrays($varType);
$scope = $this;
if (count($arrays) > 0) {
$scope = $scope->specifyExpressionType($expr->var, TypeCombinator::union(...$arrays));
}

return $scope->invalidateExpression($expr->var);
return $this->specifyExpressionType(
$expr->var,
$this->getType($expr->var)->unsetOffset($this->getType($expr->dim)),
)->invalidateExpression(
new FuncCall(new FullyQualified('count'), [new Arg($expr->var)]),
);
}

return $this;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Expand Up @@ -115,6 +115,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
return new ErrorType();
}

public function isArray(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Expand Up @@ -116,6 +116,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
return new ErrorType();
}

public function isArray(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Expand Up @@ -112,6 +112,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
return new ErrorType();
}

public function isArray(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
8 changes: 8 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Expand Up @@ -114,6 +114,14 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
if ($this->offsetType->isSuperTypeOf($offsetType)->yes()) {
return new ErrorType();
}
return $this;
}

public function isIterableAtLeastOnce(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Expand Up @@ -107,6 +107,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
return new ErrorType();
}

public function isIterable(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ArrayType.php
Expand Up @@ -255,6 +255,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
), new NonEmptyArrayType());
}

public function unsetOffset(Type $offsetType): Type
{
return $this;
}

public function isCallable(): TrinaryLogic
{
return TrinaryLogic::createMaybe()->and((new StringType())->isSuperTypeOf($this->itemType));
Expand Down
23 changes: 2 additions & 21 deletions src/Type/BooleanType.php
Expand Up @@ -2,7 +2,6 @@

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantFloatType;
use PHPStan\Type\Constant\ConstantIntegerType;
Expand All @@ -11,6 +10,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;

Expand All @@ -25,6 +25,7 @@ class BooleanType implements Type
use UndecidedBooleanTypeTrait;
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;

/** @api */
public function __construct()
Expand Down Expand Up @@ -74,26 +75,6 @@ public function toArray(): Type
);
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getOffsetValueType(Type $offsetType): Type
{
return new ErrorType();
}

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
return new ErrorType();
}

/**
* @param mixed[] $properties
*/
Expand Down
22 changes: 2 additions & 20 deletions src/Type/ClosureType.php
Expand Up @@ -23,6 +23,7 @@
use PHPStan\Type\Generic\TemplateTypeHelper;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
use function array_map;
use function array_merge;
Expand All @@ -35,6 +36,7 @@ class ClosureType implements TypeWithClassName, ParametersAcceptor

use NonGenericTypeTrait;
use UndecidedComparisonTypeTrait;
use NonOffsetAccessibleTypeTrait;

private ObjectType $objectType;

Expand Down Expand Up @@ -228,26 +230,6 @@ public function getIterableValueType(): Type
return new ErrorType();
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getOffsetValueType(Type $offsetType): Type
{
return new ErrorType();
}

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
return new ErrorType();
}

public function isCallable(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
22 changes: 2 additions & 20 deletions src/Type/FloatType.php
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
use function get_class;
Expand All @@ -24,6 +25,7 @@ class FloatType implements Type
use UndecidedBooleanTypeTrait;
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;

/** @api */
public function __construct()
Expand Down Expand Up @@ -109,26 +111,6 @@ public function toArray(): Type
);
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getOffsetValueType(Type $offsetType): Type
{
return new ErrorType();
}

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
return new ErrorType();
}

public function isArray(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
23 changes: 2 additions & 21 deletions src/Type/IntegerType.php
Expand Up @@ -2,14 +2,14 @@

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Traits\NonCallableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;

Expand All @@ -24,6 +24,7 @@ class IntegerType implements Type
use UndecidedBooleanTypeTrait;
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;

/** @api */
public function __construct()
Expand Down Expand Up @@ -75,24 +76,4 @@ public function toArray(): Type
);
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getOffsetValueType(Type $offsetType): Type
{
return new ErrorType();
}

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
return new ErrorType();
}

}
5 changes: 5 additions & 0 deletions src/Type/IntersectionType.php
Expand Up @@ -380,6 +380,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
}

public function unsetOffset(Type $offsetType): Type
{
return $this->intersectTypes(static fn (Type $type): Type => $type->unsetOffset($offsetType));
}

public function isCallable(): TrinaryLogic
{
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isCallable());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/MixedType.php
Expand Up @@ -116,6 +116,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return new self($this->isExplicitMixed);
}

public function unsetOffset(Type $offsetType): Type
{
return $this;
}

public function isCallable(): TrinaryLogic
{
if (
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NeverType.php
Expand Up @@ -171,6 +171,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return new NeverType();
}

public function unsetOffset(Type $offsetType): Type
{
return new NeverType();
}

public function isCallable(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NullType.php
Expand Up @@ -158,6 +158,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $array->setOffsetValueType($offsetType, $valueType, $unionValues);
}

public function unsetOffset(Type $offsetType): Type
{
return $this;
}

public function traverse(callable $cb): Type
{
return $this;
Expand Down
9 changes: 9 additions & 0 deletions src/Type/ObjectType.php
Expand Up @@ -877,6 +877,15 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
return $this;
}

public function unsetOffset(Type $offsetType): Type
{
if ($this->isOffsetAccessible()->no()) {
return new ErrorType();
}

return $this;
}

public function isCallable(): TrinaryLogic
{
$parametersAcceptors = $this->findCallableParametersAcceptors();
Expand Down

0 comments on commit b43c057

Please sign in to comment.