Skip to content

Commit 1537424

Browse files
committed
Assume offset value set was successful for further analysis
1 parent bee8f24 commit 1537424

File tree

7 files changed

+37
-6
lines changed

7 files changed

+37
-6
lines changed

phpstan-baseline.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ parameters:
55
count: 1
66
path: src/Analyser/DirectScopeFactory.php
77

8+
-
9+
message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#"
10+
count: 1
11+
path: src/Analyser/IgnoredErrorHelperResult.php
12+
813
-
914
message: "#^Function is_a\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#"
1015
count: 1

src/Analyser/MutatingScope.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,7 @@ private function specifyExpressionType(Expr $expr, Type $type, ?Type $nativeType
35233523
$types = [
35243524
new ArrayType(new MixedType(), new MixedType()),
35253525
new ObjectType(ArrayAccess::class),
3526+
new NullType(),
35263527
];
35273528
if ($dimType instanceof ConstantIntegerType) {
35283529
$types[] = new StringType();

src/Analyser/NodeScopeResolver.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,6 +3374,17 @@ private function processAssignVar(
33743374
foreach (array_reverse($offsetTypes) as $i => $offsetType) {
33753375
/** @var Type $offsetValueType */
33763376
$offsetValueType = array_pop($offsetValueTypeStack);
3377+
if (!$offsetValueType instanceof MixedType) {
3378+
$types = [
3379+
new ArrayType(new MixedType(), new MixedType()),
3380+
new ObjectType(ArrayAccess::class),
3381+
new NullType(),
3382+
];
3383+
if ($offsetType !== null && (new IntegerType())->isSuperTypeOf($offsetType)->yes()) {
3384+
$types[] = new StringType();
3385+
}
3386+
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
3387+
}
33773388
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
33783389
}
33793390

src/Type/NeverType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public function getOffsetValueType(Type $offsetType): Type
172172

173173
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
174174
{
175-
return new NeverType();
175+
return new ErrorType();
176176
}
177177

178178
public function unsetOffset(Type $offsetType): Type

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ public function testRule(): void
167167
'Offset \'feature_pretty…\' does not exist on array{version: non-empty-string, commit: string|null, pretty_version: string|null, feature_version: non-empty-string, feature_pretty_version?: string|null}.',
168168
504,
169169
],
170+
[
171+
"Cannot access offset 'foo' on bool.",
172+
517,
173+
],
170174
]);
171175
}
172176

@@ -248,7 +252,7 @@ public function testBug3782(): void
248252
{
249253
$this->analyse([__DIR__ . '/data/bug-3782.php'], [
250254
[
251-
'Cannot access offset (int|string) on Bug3782\HelloWorld.',
255+
'Cannot access offset (int|string) on $this(Bug3782\HelloWorld)|(ArrayAccess&Bug3782\HelloWorld).',
252256
11,
253257
],
254258
]);

tests/PHPStan/Rules/Arrays/data/nonexistent-offset.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,13 @@ private function postprocess(array $versionData): array
508508
return $versionData;
509509
}
510510
}
511+
512+
class OnBool
513+
{
514+
515+
public function doFoo(bool $b)
516+
{
517+
$b['foo'] = 1;
518+
}
519+
520+
}

tests/PHPStan/Rules/Comparison/data/bug-4708.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function GetASCConfig()
5353
{
5454
assertType('array<string>|true', $result);
5555
$result['bsw'] = 1;
56-
assertType('*ERROR*', $result); // should be non-empty-array<string|1>&hasOffsetValue('bsw', 1)
56+
assertType("non-empty-array<1|string>&hasOffsetValue('bsw', 1)", $result);
5757
}
5858
else
5959
{
@@ -62,7 +62,7 @@ function GetASCConfig()
6262
assertType('*NEVER*', $result); // should be non-empty-array<string|int>&hasOffsetValue('bsw', int)
6363
}
6464

65-
assertType('*ERROR*', $result); // should have a better result
65+
assertType("non-empty-array<1|string>&hasOffsetValue('bsw', 1)", $result); // should have an int
6666

6767
if (!isset($result['bew']))
6868
{
@@ -73,7 +73,7 @@ function GetASCConfig()
7373
$result['bew'] = (int) $result['bew'];
7474
}
7575

76-
assertType('array{bew: int}', $result); // missing bsw key
76+
assertType("non-empty-array<int|string>&hasOffsetValue('bsw', 1)", $result); // missing bsw key
7777

7878
foreach (['utc', 'ssi'] as $field)
7979
{
@@ -84,7 +84,7 @@ function GetASCConfig()
8484
}
8585
}
8686

87-
assertType("non-empty-array<'bew'|'dberror'|'result'|'ssi'|'utc', 'xyz'|int|false>", $result); // should be non-empty-array<int|string|false>
87+
assertType("non-empty-array<int|string|false>", $result);
8888

8989
return $result;
9090
}

0 commit comments

Comments
 (0)