Skip to content

Commit 32353a9

Browse files
committed
Unsetting an offset should remove non-empty-array
1 parent f09b288 commit 32353a9

3 files changed

Lines changed: 51 additions & 0 deletions

File tree

src/Type/MixedType.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection;
1717
use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection;
1818
use PHPStan\TrinaryLogic;
19+
use PHPStan\Type\Constant\ConstantArrayType;
1920
use PHPStan\Type\Constant\ConstantBooleanType;
2021
use PHPStan\Type\Generic\TemplateMixedType;
2122
use PHPStan\Type\Generic\TemplateType;
@@ -120,6 +121,9 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
120121

121122
public function unsetOffset(Type $offsetType): Type
122123
{
124+
if ($this->subtractedType !== null) {
125+
return new self($this->isExplicitMixed, TypeCombinator::remove($this->subtractedType, new ConstantArrayType([], [])));
126+
}
123127
return $this;
124128
}
125129

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ public function dataFileAsserts(): iterable
979979
yield from $this->gatherAssertTypes(__DIR__ . '/data/closure-argument-type.php');
980980
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7788.php');
981981
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7809.php');
982+
yield from $this->gatherAssertTypes(__DIR__ . '/data/composer-non-empty-array-after-unset.php');
982983
}
983984

984985
/**
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace ComposerNonEmptyArrayAfterUnset;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
/** @var mixed[] */
11+
private $config;
12+
13+
public function doFoo()
14+
{
15+
if (!empty($this->config['authors'])) {
16+
assertType("mixed~0|0.0|''|'0'|array{}|false|null", $this->config['authors']);
17+
foreach ($this->config['authors'] as $key => $author) {
18+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
19+
if (!is_array($author)) {
20+
unset($this->config['authors'][$key]);
21+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
22+
continue;
23+
}
24+
foreach (['homepage', 'email', 'name', 'role'] as $authorData) {
25+
if (isset($author[$authorData]) && !is_string($author[$authorData])) {
26+
unset($this->config['authors'][$key][$authorData]);
27+
}
28+
}
29+
if (isset($author['homepage'])) {
30+
unset($this->config['authors'][$key]['homepage']);
31+
}
32+
if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
33+
unset($this->config['authors'][$key]['email']);
34+
}
35+
if (empty($this->config['authors'][$key])) {
36+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
37+
unset($this->config['authors'][$key]);
38+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
39+
}
40+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
41+
}
42+
assertType("mixed~0|0.0|''|'0'|false|null", $this->config['authors']);
43+
}
44+
}
45+
46+
}

0 commit comments

Comments
 (0)