Skip to content

Commit 5105b0b

Browse files
committed
narrow in more cases
1 parent 9a1437f commit 5105b0b

File tree

7 files changed

+93
-13
lines changed

7 files changed

+93
-13
lines changed

src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,7 @@ public function specifyTypes(
117117
new ArrayType(new MixedType(), new MixedType()),
118118
new HasOffsetType($keyType),
119119
);
120-
} elseif (
121-
$this->phpVersion->throwsValueErrorForInternalFunctions()
122-
&& !$arrayType->isArray()->yes()
123-
) {
120+
} elseif ($this->phpVersion->throwsValueErrorForInternalFunctions()) {
124121
$specifiedTypes = $this->typeSpecifier->create(
125122
$array,
126123
new HasOffsetType($keyType),

tests/PHPStan/Analyser/TypeSpecifierTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ public static function dataCondition(): iterable
10401040
'$array' => 'non-empty-array',
10411041
],
10421042
[
1043-
'$array' => '~hasOffset(\'bar\')|hasOffset(\'foo\')',
1043+
'$array' => PHP_VERSION_ID < 80000 ? '~hasOffset(\'bar\')|hasOffset(\'foo\')' : "array<mixed~'foo', mixed> & ~hasOffset('bar')|hasOffset('foo')",
10441044
],
10451045
],
10461046
[
@@ -1055,7 +1055,7 @@ public static function dataCondition(): iterable
10551055
]),
10561056
)),
10571057
[
1058-
'$array' => '~hasOffset(\'bar\')|hasOffset(\'foo\')',
1058+
'$array' => PHP_VERSION_ID < 80000 ? '~hasOffset(\'bar\')|hasOffset(\'foo\')' : "array<mixed~'foo', mixed> & ~hasOffset('bar')|hasOffset('foo')",
10591059
],
10601060
[
10611061
'$array' => 'non-empty-array',
@@ -1070,7 +1070,7 @@ public static function dataCondition(): iterable
10701070
'$array' => 'non-empty-array&hasOffset(\'foo\')',
10711071
],
10721072
[
1073-
'$array' => '~hasOffset(\'foo\')',
1073+
'$array' => PHP_VERSION_ID < 80000 ? '~hasOffset(\'foo\')' : "array<mixed~'foo', mixed> & ~hasOffset('foo')",
10741074
],
10751075
],
10761076
[
@@ -1088,7 +1088,7 @@ public static function dataCondition(): iterable
10881088
'$array' => 'non-empty-array',
10891089
],
10901090
[
1091-
'$array' => '~hasOffset(\'bar\')|hasOffset(\'foo\')',
1091+
'$array' => PHP_VERSION_ID < 80000 ? '~hasOffset(\'bar\')|hasOffset(\'foo\')' : "array<mixed~'foo', mixed> & ~hasOffset('bar')|hasOffset('foo')",
10921092
],
10931093
],
10941094
[
@@ -1103,7 +1103,7 @@ public static function dataCondition(): iterable
11031103
]),
11041104
)),
11051105
[
1106-
'$array' => '~hasOffset(\'bar\')|hasOffset(\'foo\')',
1106+
'$array' => "array<mixed~'foo', mixed> & ~hasOffset('bar')|hasOffset('foo')",
11071107
],
11081108
[
11091109
'$array' => 'non-empty-array',
@@ -1118,7 +1118,7 @@ public static function dataCondition(): iterable
11181118
'$array' => 'non-empty-array&hasOffset(\'foo\')',
11191119
],
11201120
[
1121-
'$array' => '~hasOffset(\'foo\')',
1121+
'$array' => "array<mixed~'foo', mixed> & ~hasOffset('foo')",
11221122
],
11231123
],
11241124
[

tests/PHPStan/Analyser/nsrt/bug-13301-php8.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function doArray(array $arr) {
4646
if (array_key_exists('a', $arr)) {
4747
assertType("non-empty-array&hasOffset('a')", $arr);
4848
} else {
49-
assertType('array', $arr);
49+
assertType("array<mixed~'a', mixed>", $arr);
5050
}
5151
assertType('array', $arr);
5252
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php // lint >= 8.0
2+
3+
namespace Bug4099Php8;
4+
5+
use function PHPStan\Testing\assertNativeType;
6+
use function PHPStan\Testing\assertType;
7+
8+
class Foo
9+
{
10+
11+
/**
12+
* @param array{key: array{inner: mixed}} $arr
13+
*/
14+
function arrayHint(array $arr): void
15+
{
16+
assertType('array{key: array{inner: mixed}}', $arr);
17+
assertNativeType('array', $arr);
18+
19+
if (!array_key_exists('key', $arr)) {
20+
assertType('*NEVER*', $arr);
21+
assertNativeType("array<mixed~'key', mixed>", $arr);
22+
throw new \Exception('no key "key" found.');
23+
}
24+
assertType('array{key: array{inner: mixed}}', $arr);
25+
assertNativeType('non-empty-array&hasOffset(\'key\')', $arr);
26+
assertType('array{inner: mixed}', $arr['key']);
27+
assertNativeType('mixed', $arr['key']);
28+
29+
if (!array_key_exists('inner', $arr['key'])) {
30+
assertType('*NEVER*', $arr);
31+
assertNativeType('non-empty-array&hasOffset(\'key\')', $arr);
32+
assertType('*NEVER*', $arr['key']);
33+
assertNativeType("array<mixed~'inner', mixed>", $arr['key']);
34+
throw new \Exception('need key.inner');
35+
}
36+
37+
assertType('array{key: array{inner: mixed}}', $arr);
38+
assertNativeType('non-empty-array&hasOffset(\'key\')', $arr);
39+
}
40+
41+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php // lint < 8.0
22

33
namespace Bug4099;
44

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php // lint >= 8.0
2+
3+
declare(strict_types = 1);
4+
5+
namespace ConditionalVars;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class HelloWorld
10+
{
11+
/** @param array<mixed> $innerHits */
12+
public function conditionalVarInTernary(array $innerHits): void
13+
{
14+
if (array_key_exists('nearest_premise', $innerHits) || array_key_exists('matching_premises', $innerHits)) {
15+
assertType('non-empty-array', $innerHits);
16+
$x = array_key_exists('nearest_premise', $innerHits)
17+
? assertType("non-empty-array&hasOffset('nearest_premise')", $innerHits)
18+
: assertType("non-empty-array<mixed~'nearest_premise', mixed>", $innerHits);
19+
20+
assertType('non-empty-array', $innerHits);
21+
}
22+
assertType('array', $innerHits);
23+
}
24+
25+
/** @param array<mixed> $innerHits */
26+
public function conditionalVarInIf(array $innerHits): void
27+
{
28+
if (array_key_exists('nearest_premise', $innerHits) || array_key_exists('matching_premises', $innerHits)) {
29+
assertType('non-empty-array', $innerHits);
30+
if (array_key_exists('nearest_premise', $innerHits)) {
31+
assertType("non-empty-array&hasOffset('nearest_premise')", $innerHits);
32+
} else {
33+
assertType("non-empty-array<mixed~'nearest_premise', mixed>", $innerHits);
34+
}
35+
36+
assertType('non-empty-array', $innerHits);
37+
}
38+
assertType('array', $innerHits);
39+
}
40+
}

tests/PHPStan/Analyser/nsrt/conditional-vars.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
<?php declare(strict_types = 1);
1+
<?php // lint < 8.0
2+
3+
declare(strict_types = 1);
24

35
namespace ConditionalVars;
46

0 commit comments

Comments
 (0)