Skip to content

Commit e8e466d

Browse files
schlndhondrejmirtes
authored andcommitted
fix SplObjectStorage::removeAll/Except
1 parent 0f8a352 commit e8e466d

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

stubs/SplObjectStorage.stub

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ class SplObjectStorage implements Countable, Iterator, Serializable, ArrayAccess
4242
public function getInfo() { }
4343

4444
/**
45-
* @param \SplObjectStorage<object, mixed> $storage
45+
* @param \SplObjectStorage<*, *> $storage
4646
*/
4747
public function removeAll(SplObjectStorage $storage): void { }
4848

4949
/**
50-
* @param \SplObjectStorage<object, mixed> $storage
50+
* @param \SplObjectStorage<*, *> $storage
5151
*/
5252
public function removeAllExcept(SplObjectStorage $storage): void { }
5353

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3240,4 +3240,15 @@ public function testBug9009(): void
32403240
$this->analyse([__DIR__ . '/data/bug-9009.php'], []);
32413241
}
32423242

3243+
public function testBuSplObjectStorageRemove(): void
3244+
{
3245+
$this->checkThisOnly = false;
3246+
$this->checkNullables = true;
3247+
$this->checkUnionTypes = true;
3248+
$this->checkExplicitMixed = true;
3249+
$this->analyse([__DIR__ . '/data/bug-SplObjectStorage-remove.php'], [
3250+
// removeNoIntersect should be reported, but unfortunately it cannot be expressed by the type system.
3251+
]);
3252+
}
3253+
32433254
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace BugSplObjectStorageRemove;
4+
5+
class A {}
6+
7+
class B extends A {}
8+
9+
class C extends B {}
10+
11+
class Foo {}
12+
13+
interface BarInterface {}
14+
15+
/** @phpstan-type ObjectStorage \SplObjectStorage<B, int> */
16+
class HelloWorld
17+
{
18+
/** @var ObjectStorage */
19+
private \SplObjectStorage $foo;
20+
21+
/**
22+
* @param ObjectStorage $other
23+
* @return ObjectStorage
24+
*/
25+
public function removeSame(\SplObjectStorage $other): \SplObjectStorage
26+
{
27+
$this->foo->removeAll($other);
28+
$this->foo->removeAllExcept($other);
29+
30+
return $this->foo;
31+
}
32+
33+
/**
34+
* @param \SplObjectStorage<C, string> $other
35+
* @return ObjectStorage
36+
*/
37+
public function removeNarrower(\SplObjectStorage $other): \SplObjectStorage
38+
{
39+
$this->foo->removeAll($other);
40+
$this->foo->removeAllExcept($other);
41+
42+
return $this->foo;
43+
}
44+
45+
/**
46+
* @param \SplObjectStorage<B, string> $other
47+
* @return ObjectStorage
48+
*/
49+
public function removeWider(\SplObjectStorage $other): \SplObjectStorage
50+
{
51+
$this->foo->removeAll($other);
52+
$this->foo->removeAllExcept($other);
53+
54+
return $this->foo;
55+
}
56+
57+
/**
58+
* @param \SplObjectStorage<BarInterface, string> $other
59+
* @return ObjectStorage
60+
*/
61+
public function removePossibleIntersect(\SplObjectStorage $other): \SplObjectStorage
62+
{
63+
$this->foo->removeAll($other);
64+
$this->foo->removeAllExcept($other);
65+
66+
return $this->foo;
67+
}
68+
69+
/**
70+
* @param \SplObjectStorage<Foo, string> $other
71+
* @return ObjectStorage
72+
*/
73+
public function removeNoIntersect(\SplObjectStorage $other): \SplObjectStorage
74+
{
75+
$this->foo->removeAll($other);
76+
$this->foo->removeAllExcept($other);
77+
78+
return $this->foo;
79+
}
80+
}

0 commit comments

Comments
 (0)