Skip to content

Commit 844f569

Browse files
Infer mixed~array<mixed> | array<string> (#4425)
1 parent 67ef20b commit 844f569

File tree

5 files changed

+57
-2
lines changed

5 files changed

+57
-2
lines changed

src/Type/TypeCombinator.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ private static function intersectWithSubtractedType(
580580
Type $b,
581581
): Type
582582
{
583-
if ($a->getSubtractedType() === null) {
583+
if ($a->getSubtractedType() === null || $b instanceof NeverType) {
584584
return $a;
585585
}
586586

@@ -621,7 +621,10 @@ private static function intersectWithSubtractedType(
621621
} elseif ($isBAlreadySubtracted->yes()) {
622622
$subtractedType = self::remove($a->getSubtractedType(), $b);
623623

624-
if ($subtractedType instanceof NeverType) {
624+
if (
625+
$subtractedType instanceof NeverType
626+
|| !$subtractedType->isSuperTypeOf($b)->no()
627+
) {
625628
$subtractedType = null;
626629
}
627630

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,18 @@ public function testBug10394(): void
11001100
$this->analyse([__DIR__ . '/data/bug-10394.php'], []);
11011101
}
11021102

1103+
public function testBug12930(): void
1104+
{
1105+
$this->treatPhpDocTypesAsCertain = true;
1106+
$this->analyse([__DIR__ . '/data/bug-12930.php'], []);
1107+
}
1108+
1109+
public function testBug13628(): void
1110+
{
1111+
$this->treatPhpDocTypesAsCertain = true;
1112+
$this->analyse([__DIR__ . '/data/bug-13628.php'], []);
1113+
}
1114+
11031115
public function testBug9666(): void
11041116
{
11051117
$tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug12930;
4+
5+
/** @return mixed */
6+
function getMixed() {return \stdClass::class;}
7+
8+
$val = getMixed();
9+
if (is_string($val) && !is_a($val, \stdClass::class, true)) {
10+
throw new \Exception();
11+
}
12+
13+
echo is_string($val) ? 'string' : 'something else';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13628;
4+
5+
/**
6+
* @param mixed $param
7+
* @return string
8+
*/
9+
function test($param) {
10+
11+
$a = is_array($param) ? array_filter($param) : $param;
12+
if ($a && is_array($a)) {
13+
return 'array';
14+
}
15+
else {
16+
return 'not-array';
17+
}
18+
19+
}

tests/PHPStan/Type/TypeCombinatorTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,14 @@ public static function dataUnion(): iterable
21332133
MixedType::class,
21342134
'mixed=implicit',
21352135
],
2136+
[
2137+
[
2138+
new ArrayType(new MixedType(), new StringType()),
2139+
new MixedType(subtractedType: new ArrayType(new MixedType(), new MixedType())),
2140+
],
2141+
MixedType::class,
2142+
'mixed=implicit',
2143+
],
21362144
];
21372145

21382146
if (PHP_VERSION_ID < 80100) {

0 commit comments

Comments
 (0)