Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/Analyser/Generics/TemplateArgumentSolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ private function removeSelfBounds(Type $type, string $key): Type
return $type;
}

private function refersToKey(Type $type, string $key): bool
{
$refers = false;
TypeTraverser::map($type, function (Type $type, callable $traverse) use ($key, &$refers): Type {
if ($type instanceof UnresolvedTemplateArgumentType && $this->representative(self::key($type->getSite(), $type->getTemplateName())) === $key) {
$refers = true;
}
return $refers ? $type : $traverse($type);
});
return $refers;
}

/** @var array<string, true> */
private array $resolving = [];

Expand Down Expand Up @@ -207,7 +219,14 @@ private function resolveObservation(array $observation): Type
$initial = $observation['initial'] !== null ? $this->substituteResolutions($observation['initial']) : null;
$template = $observation['marker']->getTemplate();
$lowerBounds = [];
$key = $this->representative(self::key($observation['marker']->getSite(), $observation['marker']->getTemplateName()));
foreach ($observation['lowerBounds'] as $lowerBound) {
if ($this->refersToKey($lowerBound, $key)) {
// the object passed to its own method ($map->set($map) with
// set(TOwner $owner)) can only be bounded by itself - it says
// nothing about the argument
continue;
}
$inferred = $template->inferTemplateTypes($this->substituteResolutions($lowerBound))->getType($template->getName());
if ($inferred === null) {
continue;
Expand Down
8 changes: 8 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4560,6 +4560,14 @@ public function testBug15251(): void
$this->analyse([__DIR__ . '/data/bug-15251.php'], []);
}

public function testBug15434(): void
{
$this->checkThisOnly = false;
$this->checkNullables = true;
$this->checkUnionTypes = true;
$this->analyse([__DIR__ . '/data/bug-15434.php'], []);
}

#[RequiresPhp('>= 8.1.0')]
public function testClassConstantWildcardArguments(): void
{
Expand Down
23 changes: 23 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-15434.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);

namespace Bug15434;

class Test
{
public function testSet(): void
{
$map = new WeakAnalysingMap();
$map->set($map);
}
}

/**
* @template TOwner of object
*/
class WeakAnalysingMap
{
/**
* @param TOwner $owner
*/
public function set(object $owner): void {}
}
Loading