Skip to content

Commit 36e412f

Browse files
committed
Understand gettype when there's a union of strings on the other side
1 parent 590eb03 commit 36e412f

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

src/Analyser/TypeSpecifier.php

+26-18
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,31 @@ public function specifyTypesInCondition(
210210
}
211211
}
212212

213+
if (count($rightType->getConstantStrings()) > 0) {
214+
$types = null;
215+
foreach ($rightType->getConstantStrings() as $constantString) {
216+
$specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $constantString, $context, $scope, $rootExpr);
217+
if ($specifiedType === null) {
218+
continue;
219+
}
220+
if ($types === null) {
221+
$types = $specifiedType;
222+
continue;
223+
}
224+
225+
$types = $types->intersectWith($specifiedType);
226+
}
227+
228+
if ($types !== null) {
229+
return $types;
230+
}
231+
}
232+
213233
$expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr);
214234
if ($expressions !== null) {
215235
$exprNode = $expressions[0];
216236
$constantType = $expressions[1];
217237

218-
if ($constantType instanceof ConstantStringType) {
219-
$specifiedType = $this->specifyTypesForConstantStringBinaryExpression($exprNode, $constantType, $context, $scope, $rootExpr);
220-
if ($specifiedType !== null) {
221-
return $specifiedType;
222-
}
223-
}
224-
225238
$specifiedType = $this->specifyTypesForConstantBinaryExpression($exprNode, $constantType, $context, $scope, $rootExpr);
226239
if ($specifiedType !== null) {
227240
return $specifiedType;
@@ -1065,11 +1078,6 @@ private function specifyTypesForConstantStringBinaryExpression(
10651078
?Expr $rootExpr,
10661079
): ?SpecifiedTypes
10671080
{
1068-
$unwrappedExprNode = $exprNode;
1069-
if ($exprNode instanceof AlwaysRememberedExpr) {
1070-
$unwrappedExprNode = $exprNode->getExpr();
1071-
}
1072-
10731081
if (
10741082
$context->truthy()
10751083
&& $exprNode instanceof FuncCall
@@ -1102,10 +1110,10 @@ private function specifyTypesForConstantStringBinaryExpression(
11021110
}
11031111

11041112
if (
1105-
$unwrappedExprNode instanceof FuncCall
1106-
&& $unwrappedExprNode->name instanceof Name
1107-
&& strtolower($unwrappedExprNode->name->toString()) === 'gettype'
1108-
&& isset($unwrappedExprNode->getArgs()[0])
1113+
$exprNode instanceof FuncCall
1114+
&& $exprNode->name instanceof Name
1115+
&& strtolower($exprNode->name->toString()) === 'gettype'
1116+
&& isset($exprNode->getArgs()[0])
11091117
) {
11101118
$type = null;
11111119
if ($constantType->getValue() === 'string') {
@@ -1134,8 +1142,8 @@ private function specifyTypesForConstantStringBinaryExpression(
11341142
}
11351143

11361144
if ($type !== null) {
1137-
$callType = $this->create($unwrappedExprNode, $constantType, $context, false, $scope, $rootExpr);
1138-
$argType = $this->create($unwrappedExprNode->getArgs()[0]->value, $type, $context, false, $scope, $rootExpr);
1145+
$callType = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr);
1146+
$argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, false, $scope, $rootExpr);
11391147
return $callType->unionWith($argType);
11401148
}
11411149
}

tests/PHPStan/Analyser/data/match-expr.php

+11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ public function doGettype(int|float|bool|string|object|array $value): void
7777
};
7878
}
7979

80+
public function doGettypeUnion(int|float|bool|string|object|array $value): void
81+
{
82+
$intOrString = 'integer';
83+
if (rand(0, 1)) {
84+
$intOrString = 'string';
85+
}
86+
match (gettype($value)) {
87+
$intOrString => assertType('int|string', $value),
88+
};
89+
}
90+
8091
}
8192

8293
final class FinalFoo

0 commit comments

Comments
 (0)