Skip to content

Commit 13c22db

Browse files
phpstan-botclaude
andcommitted
Exclude constant scalar types from TemplateMixedType narrowing in TypeCombinator::intersect()
Constant scalar values like 0, '', '0' should not be narrowed from `0&T` to `T of 0` — the intersection form is more precise for constants. Only general scalar types (int, string, float, bool) are narrowed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e35ca44 commit 13c22db

2 files changed

Lines changed: 3 additions & 1 deletion

File tree

src/Type/TypeCombinator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,7 @@ public static function intersect(Type ...$types): Type
14031403
$types[$j] instanceof TemplateMixedType
14041404
&& !$types[$i] instanceof TemplateType
14051405
&& $types[$i]->isScalar()->yes()
1406+
&& !$types[$i]->isConstantScalarValue()->yes()
14061407
&& $types[$j]->getBound()->isSuperTypeOf($types[$i])->yes()
14071408
) {
14081409
$narrowed = TemplateTypeFactory::create(
@@ -1425,6 +1426,7 @@ public static function intersect(Type ...$types): Type
14251426
$types[$i] instanceof TemplateMixedType
14261427
&& !$types[$j] instanceof TemplateType
14271428
&& $types[$j]->isScalar()->yes()
1429+
&& !$types[$j]->isConstantScalarValue()->yes()
14281430
&& $types[$i]->getBound()->isSuperTypeOf($types[$j])->yes()
14291431
) {
14301432
$narrowed = TemplateTypeFactory::create(

tests/PHPStan/Analyser/nsrt/bug-4117.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function broken(int $key)
3434
if ($item) {
3535
assertType("T of mixed~(0|0.0|''|'0'|array{}|false|null) (class Bug4117Types\GenericList, argument)", $item);
3636
} else {
37-
assertType("T of 0 (class Bug4117Types\GenericList, argument)|T of '' (class Bug4117Types\GenericList, argument)|T of '0' (class Bug4117Types\GenericList, argument)|(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(list{}&T of mixed~null (class Bug4117Types\GenericList, argument))|null", $item);
37+
assertType("(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(list{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|null", $item);
3838
}
3939

4040
assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item);

0 commit comments

Comments
 (0)