Skip to content

Commit 28c187f

Browse files
committed
Narrow types after cast in generator based Handlers
1 parent d7482af commit 28c187f

File tree

5 files changed

+88
-13
lines changed

5 files changed

+88
-13
lines changed

src/Analyser/Generator/ExprHandler/CastBoolHandler.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
use Generator;
66
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Name\FullyQualified;
78
use PhpParser\Node\Stmt;
89
use PHPStan\Analyser\ExpressionContext;
910
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
1011
use PHPStan\Analyser\Generator\ExprAnalysisResult;
1112
use PHPStan\Analyser\Generator\ExprHandler;
1213
use PHPStan\Analyser\Generator\GeneratorScope;
13-
use PHPStan\Analyser\SpecifiedTypes;
14+
use PHPStan\Analyser\Generator\NoopNodeCallback;
1415
use PHPStan\DependencyInjection\AutowiredService;
1516

1617
/**
@@ -34,6 +35,7 @@ public function analyseExpr(
3435
): Generator
3536
{
3637
$exprResult = yield new ExprAnalysisRequest($stmt, $expr->expr, $scope, $context->enterDeep(), $alternativeNodeCallback);
38+
$specifiedExprResult = yield new ExprAnalysisRequest($stmt, new Expr\BinaryOp\Equal($expr->expr, new Expr\ConstFetch(new FullyQualified('true'))), $scope, $context->enterDeep(), new NoopNodeCallback());
3739

3840
return new ExprAnalysisResult(
3941
$exprResult->type->toBoolean(),
@@ -43,9 +45,9 @@ public function analyseExpr(
4345
isAlwaysTerminating: false,
4446
throwPoints: [],
4547
impurePoints: [],
46-
specifiedTruthyTypes: new SpecifiedTypes(),
47-
specifiedFalseyTypes: new SpecifiedTypes(),
48-
specifiedNullTypes: new SpecifiedTypes(),
48+
specifiedTruthyTypes: $specifiedExprResult->specifiedTruthyTypes,
49+
specifiedFalseyTypes: $specifiedExprResult->specifiedFalseyTypes,
50+
specifiedNullTypes: $specifiedExprResult->specifiedNullTypes,
4951
);
5052
}
5153

src/Analyser/Generator/ExprHandler/CastDoubleHandler.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
use Generator;
66
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Scalar\DNumber;
8+
use PhpParser\Node\Scalar\LNumber;
79
use PhpParser\Node\Stmt;
810
use PHPStan\Analyser\ExpressionContext;
911
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
1012
use PHPStan\Analyser\Generator\ExprAnalysisResult;
1113
use PHPStan\Analyser\Generator\ExprHandler;
1214
use PHPStan\Analyser\Generator\GeneratorScope;
15+
use PHPStan\Analyser\Generator\NoopNodeCallback;
1316
use PHPStan\Analyser\SpecifiedTypes;
1417
use PHPStan\DependencyInjection\AutowiredService;
1518

@@ -34,6 +37,7 @@ public function analyseExpr(
3437
): Generator
3538
{
3639
$exprResult = yield new ExprAnalysisRequest($stmt, $expr->expr, $scope, $context->enterDeep(), $alternativeNodeCallback);
40+
$specifiedExprResult = yield new ExprAnalysisRequest($stmt, new Expr\BinaryOp\Equal($expr->expr, new DNumber(0.0)), $scope, $context->enterDeep(), new NoopNodeCallback());
3741

3842
return new ExprAnalysisResult(
3943
$exprResult->type->toFloat(),
@@ -43,9 +47,9 @@ public function analyseExpr(
4347
isAlwaysTerminating: false,
4448
throwPoints: [],
4549
impurePoints: [],
46-
specifiedTruthyTypes: new SpecifiedTypes(),
47-
specifiedFalseyTypes: new SpecifiedTypes(),
48-
specifiedNullTypes: new SpecifiedTypes(),
50+
specifiedTruthyTypes: $specifiedExprResult->specifiedTruthyTypes,
51+
specifiedFalseyTypes: $specifiedExprResult->specifiedFalseyTypes,
52+
specifiedNullTypes: $specifiedExprResult->specifiedNullTypes,
4953
);
5054
}
5155

src/Analyser/Generator/ExprHandler/CastIntHandler.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
use Generator;
66
use PhpParser\Node\Expr;
77
use PhpParser\Node\Expr\Cast\Int_;
8+
use PhpParser\Node\Scalar\LNumber;
9+
use PhpParser\Node\Scalar\String_;
810
use PhpParser\Node\Stmt;
911
use PHPStan\Analyser\ExpressionContext;
1012
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
1113
use PHPStan\Analyser\Generator\ExprAnalysisResult;
1214
use PHPStan\Analyser\Generator\ExprHandler;
1315
use PHPStan\Analyser\Generator\GeneratorScope;
16+
use PHPStan\Analyser\Generator\NoopNodeCallback;
1417
use PHPStan\Analyser\SpecifiedTypes;
1518
use PHPStan\DependencyInjection\AutowiredService;
1619

@@ -35,6 +38,7 @@ public function analyseExpr(
3538
): Generator
3639
{
3740
$exprResult = yield new ExprAnalysisRequest($stmt, $expr->expr, $scope, $context->enterDeep(), $alternativeNodeCallback);
41+
$specifiedExprResult = yield new ExprAnalysisRequest($stmt, new Expr\BinaryOp\Equal($expr->expr, new LNumber(0)), $scope, $context->enterDeep(), new NoopNodeCallback());
3842

3943
return new ExprAnalysisResult(
4044
$exprResult->type->toInteger(),
@@ -44,9 +48,9 @@ public function analyseExpr(
4448
isAlwaysTerminating: false,
4549
throwPoints: [],
4650
impurePoints: [],
47-
specifiedTruthyTypes: new SpecifiedTypes(),
48-
specifiedFalseyTypes: new SpecifiedTypes(),
49-
specifiedNullTypes: new SpecifiedTypes(),
51+
specifiedTruthyTypes: $specifiedExprResult->specifiedTruthyTypes,
52+
specifiedFalseyTypes: $specifiedExprResult->specifiedFalseyTypes,
53+
specifiedNullTypes: $specifiedExprResult->specifiedNullTypes,
5054
);
5155
}
5256

src/Analyser/Generator/ExprHandler/CastStringHandler.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
use Generator;
66
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Name\FullyQualified;
8+
use PhpParser\Node\Scalar\String_;
79
use PhpParser\Node\Stmt;
810
use PHPStan\Analyser\ExpressionContext;
911
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
1012
use PHPStan\Analyser\Generator\ExprAnalysisResult;
1113
use PHPStan\Analyser\Generator\ExprHandler;
1214
use PHPStan\Analyser\Generator\GeneratorScope;
15+
use PHPStan\Analyser\Generator\NoopNodeCallback;
1316
use PHPStan\Analyser\SpecifiedTypes;
1417
use PHPStan\DependencyInjection\AutowiredService;
1518

@@ -34,6 +37,7 @@ public function analyseExpr(
3437
): Generator
3538
{
3639
$exprResult = yield new ExprAnalysisRequest($stmt, $expr->expr, $scope, $context->enterDeep(), $alternativeNodeCallback);
40+
$specifiedExprResult = yield new ExprAnalysisRequest($stmt, new Expr\BinaryOp\Equal($expr->expr, new String_('')), $scope, $context->enterDeep(), new NoopNodeCallback());
3741

3842
return new ExprAnalysisResult(
3943
$exprResult->type->toString(),
@@ -43,9 +47,9 @@ public function analyseExpr(
4347
isAlwaysTerminating: false,
4448
throwPoints: [],
4549
impurePoints: [],
46-
specifiedTruthyTypes: new SpecifiedTypes(),
47-
specifiedFalseyTypes: new SpecifiedTypes(),
48-
specifiedNullTypes: new SpecifiedTypes(),
50+
specifiedTruthyTypes: $specifiedExprResult->specifiedTruthyTypes,
51+
specifiedFalseyTypes: $specifiedExprResult->specifiedFalseyTypes,
52+
specifiedNullTypes: $specifiedExprResult->specifiedNullTypes,
4953
);
5054
}
5155

tests/PHPStan/Analyser/Generator/data/gnsr.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,64 @@ function (array $a): void {
555555

556556
assertType("array", $a);
557557
};
558+
559+
class CastNarrowing {
560+
/**
561+
* @param int $i2
562+
* @param mixed $m2
563+
*/
564+
public function doCastNarrowing(
565+
int $i, mixed $m,
566+
$i2, $m2
567+
): void
568+
{
569+
if ((bool) $i) {
570+
assertNativeType('int<min, -1>|int<1, max>', $i);
571+
} else {
572+
assertNativeType('0', $i);
573+
}
574+
assertNativeType('int', $i);
575+
576+
if ((bool) $i2) {
577+
assertType('int<min, -1>|int<1, max>', $i2);
578+
} else {
579+
assertType('0', $i2);
580+
}
581+
assertType('int', $i2);
582+
583+
if ((bool) $m) {
584+
assertNativeType("mixed~(0|0.0|''|'0'|array{}|false|null)", $m);
585+
} else {
586+
assertNativeType("0|0.0|''|'0'|array{}|false|null", $m);
587+
}
588+
assertNativeType('mixed', $m);
589+
590+
if ((bool) $m2) {
591+
assertType("mixed~(0|0.0|''|'0'|array{}|false|null)", $m2);
592+
} else {
593+
assertType("0|0.0|''|'0'|array{}|false|null", $m2);
594+
}
595+
assertType('mixed', $m2);
596+
597+
if ((string) $m2) {
598+
assertType("mixed~(0|0.0|''|'0'|array{}|false|null)", $m2);
599+
} else {
600+
assertType("0|0.0|''|'0'|array{}|false|null", $m2);
601+
}
602+
assertType('mixed', $m2);
603+
604+
if ((int) $m2) {
605+
assertType("mixed~(0|0.0|''|'0'|array{}|false|null)", $m2);
606+
} else {
607+
assertType("0|0.0|''|'0'|array{}|false|null", $m2);
608+
}
609+
assertType('mixed', $m2);
610+
611+
if ((float) $m2) {
612+
assertType("mixed~(0|0.0|''|'0'|array{}|false|null)", $m2);
613+
} else {
614+
assertType("0|0.0|''|'0'|array{}|false|null", $m2);
615+
}
616+
assertType('mixed', $m2);
617+
}
618+
}

0 commit comments

Comments
 (0)