Skip to content

Commit

Permalink
Assume offset value set was successful for further analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Aug 4, 2022
1 parent bee8f24 commit 1537424
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 6 deletions.
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ parameters:
count: 1
path: src/Analyser/DirectScopeFactory.php

-
message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#"
count: 1
path: src/Analyser/IgnoredErrorHelperResult.php

-
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\\.$#"
count: 1
Expand Down
1 change: 1 addition & 0 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -3523,6 +3523,7 @@ private function specifyExpressionType(Expr $expr, Type $type, ?Type $nativeType
$types = [
new ArrayType(new MixedType(), new MixedType()),
new ObjectType(ArrayAccess::class),
new NullType(),
];
if ($dimType instanceof ConstantIntegerType) {
$types[] = new StringType();
Expand Down
11 changes: 11 additions & 0 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3374,6 +3374,17 @@ private function processAssignVar(
foreach (array_reverse($offsetTypes) as $i => $offsetType) {
/** @var Type $offsetValueType */
$offsetValueType = array_pop($offsetValueTypeStack);
if (!$offsetValueType instanceof MixedType) {
$types = [
new ArrayType(new MixedType(), new MixedType()),
new ObjectType(ArrayAccess::class),
new NullType(),
];
if ($offsetType !== null && (new IntegerType())->isSuperTypeOf($offsetType)->yes()) {
$types[] = new StringType();
}
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
}
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Type/NeverType.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function getOffsetValueType(Type $offsetType): Type

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
return new NeverType();
return new ErrorType();
}

public function unsetOffset(Type $offsetType): Type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ public function testRule(): void
'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}.',
504,
],
[
"Cannot access offset 'foo' on bool.",
517,
],
]);
}

Expand Down Expand Up @@ -248,7 +252,7 @@ public function testBug3782(): void
{
$this->analyse([__DIR__ . '/data/bug-3782.php'], [
[
'Cannot access offset (int|string) on Bug3782\HelloWorld.',
'Cannot access offset (int|string) on $this(Bug3782\HelloWorld)|(ArrayAccess&Bug3782\HelloWorld).',
11,
],
]);
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Rules/Arrays/data/nonexistent-offset.php
Original file line number Diff line number Diff line change
Expand Up @@ -508,3 +508,13 @@ private function postprocess(array $versionData): array
return $versionData;
}
}

class OnBool
{

public function doFoo(bool $b)
{
$b['foo'] = 1;
}

}
8 changes: 4 additions & 4 deletions tests/PHPStan/Rules/Comparison/data/bug-4708.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function GetASCConfig()
{
assertType('array<string>|true', $result);
$result['bsw'] = 1;
assertType('*ERROR*', $result); // should be non-empty-array<string|1>&hasOffsetValue('bsw', 1)
assertType("non-empty-array<1|string>&hasOffsetValue('bsw', 1)", $result);
}
else
{
Expand All @@ -62,7 +62,7 @@ function GetASCConfig()
assertType('*NEVER*', $result); // should be non-empty-array<string|int>&hasOffsetValue('bsw', int)
}

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

if (!isset($result['bew']))
{
Expand All @@ -73,7 +73,7 @@ function GetASCConfig()
$result['bew'] = (int) $result['bew'];
}

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

foreach (['utc', 'ssi'] as $field)
{
Expand All @@ -84,7 +84,7 @@ function GetASCConfig()
}
}

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

return $result;
}

0 comments on commit 1537424

Please sign in to comment.