Skip to content

Commit

Permalink
fix SplObjectStorage::removeAll/Except
Browse files Browse the repository at this point in the history
  • Loading branch information
schlndh authored and ondrejmirtes committed Mar 20, 2024
1 parent 0f8a352 commit e8e466d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 2 deletions.
4 changes: 2 additions & 2 deletions stubs/SplObjectStorage.stub
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ class SplObjectStorage implements Countable, Iterator, Serializable, ArrayAccess
public function getInfo() { }

/**
* @param \SplObjectStorage<object, mixed> $storage
* @param \SplObjectStorage<*, *> $storage
*/
public function removeAll(SplObjectStorage $storage): void { }

/**
* @param \SplObjectStorage<object, mixed> $storage
* @param \SplObjectStorage<*, *> $storage
*/
public function removeAllExcept(SplObjectStorage $storage): void { }

Expand Down
11 changes: 11 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3240,4 +3240,15 @@ public function testBug9009(): void
$this->analyse([__DIR__ . '/data/bug-9009.php'], []);
}

public function testBuSplObjectStorageRemove(): void
{
$this->checkThisOnly = false;
$this->checkNullables = true;
$this->checkUnionTypes = true;
$this->checkExplicitMixed = true;
$this->analyse([__DIR__ . '/data/bug-SplObjectStorage-remove.php'], [
// removeNoIntersect should be reported, but unfortunately it cannot be expressed by the type system.
]);
}

}
80 changes: 80 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-SplObjectStorage-remove.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php declare(strict_types = 1);

namespace BugSplObjectStorageRemove;

class A {}

class B extends A {}

class C extends B {}

class Foo {}

interface BarInterface {}

/** @phpstan-type ObjectStorage \SplObjectStorage<B, int> */
class HelloWorld
{
/** @var ObjectStorage */
private \SplObjectStorage $foo;

/**
* @param ObjectStorage $other
* @return ObjectStorage
*/
public function removeSame(\SplObjectStorage $other): \SplObjectStorage
{
$this->foo->removeAll($other);
$this->foo->removeAllExcept($other);

return $this->foo;
}

/**
* @param \SplObjectStorage<C, string> $other
* @return ObjectStorage
*/
public function removeNarrower(\SplObjectStorage $other): \SplObjectStorage
{
$this->foo->removeAll($other);
$this->foo->removeAllExcept($other);

return $this->foo;
}

/**
* @param \SplObjectStorage<B, string> $other
* @return ObjectStorage
*/
public function removeWider(\SplObjectStorage $other): \SplObjectStorage
{
$this->foo->removeAll($other);
$this->foo->removeAllExcept($other);

return $this->foo;
}

/**
* @param \SplObjectStorage<BarInterface, string> $other
* @return ObjectStorage
*/
public function removePossibleIntersect(\SplObjectStorage $other): \SplObjectStorage
{
$this->foo->removeAll($other);
$this->foo->removeAllExcept($other);

return $this->foo;
}

/**
* @param \SplObjectStorage<Foo, string> $other
* @return ObjectStorage
*/
public function removeNoIntersect(\SplObjectStorage $other): \SplObjectStorage
{
$this->foo->removeAll($other);
$this->foo->removeAllExcept($other);

return $this->foo;
}
}

0 comments on commit e8e466d

Please sign in to comment.