Skip to content

Commit

Permalink
work on types in ImpossibleTypeHelper per Expr
Browse files Browse the repository at this point in the history
  • Loading branch information
clxmstaab committed Mar 25, 2022
1 parent 3056e7c commit 1cb657f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 26 deletions.
68 changes: 57 additions & 11 deletions src/Rules/Comparison/ImpossibleCheckTypeHelper.php
Expand Up @@ -22,7 +22,6 @@
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\VerbosityLevel;
use function array_column;
use function array_map;
use function array_pop;
use function count;
Expand Down Expand Up @@ -182,6 +181,21 @@ public function findSpecifiedType(
$sureTypes = $specifiedTypes->getSureTypes();
$sureNotTypes = $specifiedTypes->getSureNotTypes();

return $this->findSpecifiedSureAndSureNotTypes($scope, $node, $sureTypes, $sureNotTypes);
}

/**
* @param array<string, array{Expr, Type}> $sureTypes
* @param array<string, array{Expr, Type}> $sureNotTypes
* @return void
*/
private function findSpecifiedSureAndSureNotTypes(
Scope $scope,
Expr $node,
array $sureTypes,
array $sureNotTypes,
)
{
$isSpecified = static function (Expr $expr) use ($scope, $node): bool {
if ($expr === $node) {
return true;
Expand Down Expand Up @@ -252,11 +266,20 @@ public function findSpecifiedType(
return null;
}
}
$types = TypeCombinator::union(
...array_column($sureTypes, 1),
);
if ($types instanceof NeverType) {
return false;

foreach ($sureTypes as $sureType) {
$types = $this->sureUnionTypes($sureTypes, $sureType[0]);

if (count($types) === 1 && count($sureNotTypes) === 0) {
$findTypes = $this->findSpecifiedSureAndSureNotTypes($scope, $node, [$sureType], $sureNotTypes);
if ($findTypes !== null) {
return $findTypes;
}
}

if (TypeCombinator::union(...$types) instanceof NeverType) {
return false;
}
}
}

Expand All @@ -266,17 +289,40 @@ public function findSpecifiedType(
return null;
}
}
$types = TypeCombinator::union(
...array_column($sureNotTypes, 1),
);
if ($types instanceof NeverType) {
return true;

foreach ($sureNotTypes as $sureNotType) {
$types = $this->sureUnionTypes($sureNotTypes, $sureNotType[0]);

if (count($types) === 1 && count($sureTypes) === 0) {
$findTypes = $this->findSpecifiedSureAndSureNotTypes($scope, $node, $sureTypes, [$sureNotType]);
if ($findTypes !== null) {
return $findTypes;
}
}

if (TypeCombinator::union(...$types) instanceof NeverType) {
return true;
}
}
}

return null;
}

private function sureUnionTypes(array $sureOrSureNotTypes, Expr $expr): array
{
$types = [];
foreach ($sureOrSureNotTypes as [$sureExpr, $type]) {
if ($sureExpr !== $expr) {
continue;
}

$types[] = $type;
}

return $types;
}

/**
* @param Node\Arg[] $args
*/
Expand Down
27 changes: 12 additions & 15 deletions src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php
Expand Up @@ -10,11 +10,10 @@
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\FunctionTypeSpecifyingExtension;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\UnionType;
use function count;
use function strtolower;

Expand Down Expand Up @@ -48,19 +47,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
$arrayValueType = $arrayType->getIterableValueType();

$specifiedTypes = new SpecifiedTypes([], []);
if ($context->true()
&& $arrayType->isArray()->yes()
&& !$arrayType->isIterableAtLeastOnce()->yes()
&& !($arrayType instanceof ConstantArrayType && $arrayType->isEmpty())
&& !$arrayType instanceof UnionType) {
$specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create(
$node->getArgs()[1]->value,
new NonEmptyArrayType(),
$context,
false,
$scope,
));
}

if (
$context->truthy()
Expand All @@ -75,6 +61,17 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
));
}

if ($context->true()
&& $arrayType->isArray()->yes()) {
$specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create(
$node->getArgs()[1]->value,
TypeCombinator::intersect($arrayType, new NonEmptyArrayType()),
$context,
false,
$scope,
));
}

return $specifiedTypes;
}

Expand Down

0 comments on commit 1cb657f

Please sign in to comment.