Skip to content

Commit

Permalink
Understand gettype when there's a union of strings on the other side
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 19, 2023
1 parent 590eb03 commit 36e412f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
44 changes: 26 additions & 18 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,31 @@ public function specifyTypesInCondition(
}
}

if (count($rightType->getConstantStrings()) > 0) {
$types = null;
foreach ($rightType->getConstantStrings() as $constantString) {
$specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $constantString, $context, $scope, $rootExpr);
if ($specifiedType === null) {
continue;
}
if ($types === null) {
$types = $specifiedType;
continue;
}

$types = $types->intersectWith($specifiedType);
}

if ($types !== null) {
return $types;
}
}

$expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr);
if ($expressions !== null) {
$exprNode = $expressions[0];
$constantType = $expressions[1];

if ($constantType instanceof ConstantStringType) {
$specifiedType = $this->specifyTypesForConstantStringBinaryExpression($exprNode, $constantType, $context, $scope, $rootExpr);
if ($specifiedType !== null) {
return $specifiedType;
}
}

$specifiedType = $this->specifyTypesForConstantBinaryExpression($exprNode, $constantType, $context, $scope, $rootExpr);
if ($specifiedType !== null) {
return $specifiedType;
Expand Down Expand Up @@ -1065,11 +1078,6 @@ private function specifyTypesForConstantStringBinaryExpression(
?Expr $rootExpr,
): ?SpecifiedTypes
{
$unwrappedExprNode = $exprNode;
if ($exprNode instanceof AlwaysRememberedExpr) {
$unwrappedExprNode = $exprNode->getExpr();
}

if (
$context->truthy()
&& $exprNode instanceof FuncCall
Expand Down Expand Up @@ -1102,10 +1110,10 @@ private function specifyTypesForConstantStringBinaryExpression(
}

if (
$unwrappedExprNode instanceof FuncCall
&& $unwrappedExprNode->name instanceof Name
&& strtolower($unwrappedExprNode->name->toString()) === 'gettype'
&& isset($unwrappedExprNode->getArgs()[0])
$exprNode instanceof FuncCall
&& $exprNode->name instanceof Name
&& strtolower($exprNode->name->toString()) === 'gettype'
&& isset($exprNode->getArgs()[0])
) {
$type = null;
if ($constantType->getValue() === 'string') {
Expand Down Expand Up @@ -1134,8 +1142,8 @@ private function specifyTypesForConstantStringBinaryExpression(
}

if ($type !== null) {
$callType = $this->create($unwrappedExprNode, $constantType, $context, false, $scope, $rootExpr);
$argType = $this->create($unwrappedExprNode->getArgs()[0]->value, $type, $context, false, $scope, $rootExpr);
$callType = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr);
$argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, false, $scope, $rootExpr);
return $callType->unionWith($argType);
}
}
Expand Down
11 changes: 11 additions & 0 deletions tests/PHPStan/Analyser/data/match-expr.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ public function doGettype(int|float|bool|string|object|array $value): void
};
}

public function doGettypeUnion(int|float|bool|string|object|array $value): void
{
$intOrString = 'integer';
if (rand(0, 1)) {
$intOrString = 'string';
}
match (gettype($value)) {
$intOrString => assertType('int|string', $value),
};
}

}

final class FinalFoo
Expand Down

0 comments on commit 36e412f

Please sign in to comment.