Skip to content

Commit c93e80c

Browse files
Fix NumericString to array key
1 parent 9cd58b5 commit c93e80c

File tree

8 files changed

+64
-12
lines changed

8 files changed

+64
-12
lines changed

src/Type/Accessory/AccessoryNumericStringType.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,13 @@ public function toArray(): Type
229229

230230
public function toArrayKey(): Type
231231
{
232-
return new IntegerType();
232+
return new UnionType([
233+
new IntegerType(),
234+
new IntersectionType([
235+
new StringType(),
236+
new AccessoryNumericStringType(),
237+
]),
238+
]);
233239
}
234240

235241
public function isNull(): TrinaryLogic

src/Type/Constant/ConstantArrayType.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,17 @@ public function findTypeAndMethodNames(): array
609609

610610
public function hasOffsetValueType(Type $offsetType): TrinaryLogic
611611
{
612-
$offsetType = $offsetType->toArrayKey();
612+
$offsetArrayKeyType = $offsetType->toArrayKey();
613+
614+
return $this->recursiveHasOffsetValueType($offsetArrayKeyType);
615+
}
616+
617+
private function recursiveHasOffsetValueType(Type $offsetType): TrinaryLogic
618+
{
613619
if ($offsetType instanceof UnionType) {
614620
$results = [];
615621
foreach ($offsetType->getTypes() as $innerType) {
616-
$results[] = $this->hasOffsetValueType($innerType);
622+
$results[] = $this->recursiveHasOffsetValueType($innerType);
617623
}
618624

619625
return TrinaryLogic::extremeIdentity(...$results);
@@ -623,7 +629,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic
623629
if ($finiteTypes !== []) {
624630
$results = [];
625631
foreach ($finiteTypes as $innerType) {
626-
$results[] = $this->hasOffsetValueType($innerType);
632+
$results[] = $this->recursiveHasOffsetValueType($innerType);
627633
}
628634

629635
return TrinaryLogic::extremeIdentity(...$results);

src/Type/IntersectionType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,10 @@ public function toArray(): Type
10291029
public function toArrayKey(): Type
10301030
{
10311031
if ($this->isNumericString()->yes()) {
1032-
return new IntegerType();
1032+
return new UnionType([
1033+
new IntegerType(),
1034+
$this,
1035+
]);
10331036
}
10341037

10351038
if ($this->isString()->yes()) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function doLorem(
5252
{
5353
$a = [];
5454
$a[$numericString] = 'foo';
55-
assertType('non-empty-array<int, \'foo\'>', $a);
55+
assertType('non-empty-array<int|numeric-string, \'foo\'>', $a);
5656
}
5757

5858
}

tests/PHPStan/Analyser/nsrt/isset-coalesce-empty-type.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ class Bug4671
296296
*/
297297
public function doFoo(int $intput, array $strings): void
298298
{
299-
assertType('false', isset($strings[(string) $intput]));
299+
assertType('bool', isset($strings[(string) $intput]));
300300
}
301301

302302
}

tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,17 @@ public function testBug11337(): void
10661066

10671067
public function testBug10715(): void
10681068
{
1069-
$this->analyse([__DIR__ . '/data/bug-10715.php'], []);
1069+
$this->analyse([__DIR__.'/data/bug-10715.php'], []);
1070+
}
1071+
1072+
public function testBug4163(): void
1073+
{
1074+
$this->analyse([__DIR__ . '/data/bug-4163.php'], [
1075+
[
1076+
'Method Bug4163\HelloWorld::lall() should return array<string, string> but returns array<int|string, string>.',
1077+
28,
1078+
],
1079+
]);
10701080
}
10711081

10721082
public function testBug11663(): void
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug4163;
4+
5+
class HelloWorld
6+
{
7+
/**
8+
* @phpstan-var numeric
9+
*/
10+
public $lall = 0;
11+
12+
/**
13+
* @phpstan-return array<string, string>
14+
*/
15+
function lall() {
16+
$helloCollection = [new HelloWorld(), new HelloWorld()];
17+
$result = [];
18+
19+
foreach ($helloCollection as $hello) {
20+
$key = (string)$hello->lall;
21+
22+
if (!isset($result[$key])) {
23+
$lall = 'do_something_here';
24+
$result[$key] = $lall;
25+
}
26+
}
27+
28+
return $result;
29+
}
30+
}

tests/PHPStan/Rules/Variables/IssetRuleTest.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,7 @@ public function testBug4671(): void
233233
{
234234
$this->treatPhpDocTypesAsCertain = true;
235235
$this->strictUnnecessaryNullsafePropertyFetch = false;
236-
$this->analyse([__DIR__ . '/data/bug-4671.php'], [[
237-
'Offset numeric-string on array<string, string> in isset() does not exist.',
238-
13,
239-
]]);
236+
$this->analyse([__DIR__ . '/data/bug-4671.php'], []);
240237
}
241238

242239
public function testVariableCertaintyInIsset(): void

0 commit comments

Comments
 (0)