Skip to content

Commit

Permalink
Improve unsetting constant offsets on array
Browse files Browse the repository at this point in the history
  • Loading branch information
rvanvelzen authored and ondrejmirtes committed Sep 26, 2022
1 parent 542e3f9 commit b7973e4
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 7 deletions.
14 changes: 14 additions & 0 deletions src/Type/ArrayType.php
Expand Up @@ -297,6 +297,20 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni

public function unsetOffset(Type $offsetType): Type
{
$offsetType = self::castToArrayKeyType($offsetType);

if (
($offsetType instanceof ConstantIntegerType || $offsetType instanceof ConstantStringType)
&& !$this->keyType->isSuperTypeOf($offsetType)->no()
) {
$keyType = TypeCombinator::remove($this->keyType, $offsetType);
if ($keyType instanceof NeverType) {
return new ConstantArrayType([], []);
}

return new self($keyType, $this->itemType);
}

return $this;
}

Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1043,6 +1043,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8017.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8004.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/global-namespace.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-offset-unset.php');
}

/**
Expand Down
16 changes: 16 additions & 0 deletions tests/PHPStan/Analyser/data/array-offset-unset.php
@@ -0,0 +1,16 @@
<?php

namespace ArrayOffsetUnset;

use function PHPStan\Testing\assertType;

/**
* @param array<0|1, mixed> $list
*/
function foo(array $list) {
assertType('array<0|1, mixed>', $list);
unset($list[0]);
assertType('array<1, mixed>', $list);
unset($list[1]);
assertType('array{}', $list);
}
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/bug-2648.php
Expand Up @@ -15,7 +15,7 @@ public function doFoo(array $list): void
if (count($list) > 1) {
assertType('int<2, max>', count($list));
unset($list['fooo']);
assertType('array<bool>', $list);
assertType("array<mixed~'fooo', bool>", $list);
assertType('int<0, max>', count($list));
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/data/bug-4016.php
Expand Up @@ -17,7 +17,7 @@ public function doFoo(array $a): void
assertType('non-empty-array<int, int>', $a);

unset($a[0]);
assertType('array<int, int>', $a);
assertType('array<int<min, -1>|int<1, max>, int>', $a);
}

/**
Expand All @@ -30,7 +30,7 @@ public function doBar(array $a): void
assertType('non-empty-array<int, int>&hasOffsetValue(1, 2)', $a);

unset($a[1]);
assertType('array<int, int>', $a);
assertType('array<int<min, 0>|int<2, max>, int>', $a);
}

}
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/bug-6399.php
Expand Up @@ -54,7 +54,7 @@ public function doBar(array $a): void
{
assertType('non-empty-array', $a);
unset($a[1]);
assertType('array', $a);
assertType('array<mixed~1, mixed>', $a);
}

}
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/composer-array-bug.php
Expand Up @@ -49,7 +49,7 @@ public function doFoo(): void

if (empty($this->config['authors'])) {
unset($this->config['authors']);
assertType("array", $this->config);
assertType("array<mixed~'authors', mixed>", $this->config);
} else {
assertType("array&hasOffsetValue('authors', mixed~0|0.0|''|'0'|array{}|false|null)", $this->config);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/list-type.php
Expand Up @@ -86,7 +86,7 @@ public function withFullListFunctionality(): void
$list[] = '1';
$list[] = '2';
unset($list[0]);//break list behaviour
assertType('array<int, mixed>', $list);
assertType('array<int<min, -1>|int<1, max>, mixed>', $list);

/** @var list $list2 */
$list2 = [];
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Variables/data/bug-3391.php
Expand Up @@ -26,7 +26,7 @@ public function test()

unset($data['id']);

assertType("array&hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')", $data);
assertType("array<mixed~'id', mixed>&hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')", $data);
return $data;
}
}

0 comments on commit b7973e4

Please sign in to comment.