Skip to content

Commit ac59fc8

Browse files
phpstan-botclaude
authored andcommitted
Add tests for impure receiver chain and impure arguments
Tests cover: - Named constructor: Repository::create()->getAll() with impure create() - Chained named constructor: Repository::create()->getEntity()->getValue() - Named constructor property: Repository::create()->name - Impure argument: $repository->getAllFor(Repository::create()) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 51b2db1 commit ac59fc8

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

tests/PHPStan/Analyser/nsrt/bug-8985.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public function getAll(): array
2929
return [new Entity('test')];
3030
}
3131

32+
/** @return array<int, Entity> */
33+
public function getAllFor(mixed $filter): array
34+
{
35+
return [new Entity('test')];
36+
}
37+
3238
public string $name = 'default';
3339

3440
/** @return array<int, Entity> */
@@ -42,6 +48,12 @@ public function getEntity(): Entity
4248
return new Entity('test');
4349
}
4450

51+
/** @phpstan-impure */
52+
public static function create(): self
53+
{
54+
return new self();
55+
}
56+
4557
public const MY_CONST = 'const_value';
4658
}
4759

@@ -109,3 +121,28 @@ function testClassConstFetchOnUnknownClass(string $class, string $anotherClass):
109121
$class = $anotherClass;
110122
assertType("*ERROR*", (new $class())::MY_CONST);
111123
}
124+
125+
function testNamedConstructor(): void {
126+
assert(Repository::create()->getAll() === []);
127+
128+
$all = Repository::create()->getAll();
129+
assertType('array<int, Bug8985\Entity>', $all);
130+
}
131+
132+
function testNamedConstructorChained(): void {
133+
assert(Repository::create()->getEntity()->getValue() === 'specific');
134+
135+
assertType('string', Repository::create()->getEntity()->getValue());
136+
}
137+
138+
function testNamedConstructorProperty(): void {
139+
assert(Repository::create()->name === 'foo');
140+
141+
assertType('string', Repository::create()->name);
142+
}
143+
144+
function testImpureArgument(Repository $repository): void {
145+
assert($repository->getAllFor(Repository::create()) === []);
146+
147+
assertType('array<int, Bug8985\Entity>', $repository->getAllFor(Repository::create()));
148+
}

tests/PHPStan/Rules/Arrays/data/bug-8985.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,33 @@ public function getAll(): array
2323
{
2424
return [new Entity('test')];
2525
}
26+
27+
/** @return array<int, Entity> */
28+
public function getAllFor(mixed $filter): array
29+
{
30+
return [new Entity('test')];
31+
}
32+
33+
/** @phpstan-impure */
34+
public static function create(): self
35+
{
36+
return new self();
37+
}
2638
}
2739

2840
assert((new Repository())->getAll() === []);
2941

3042
$all = (new Repository())->getAll();
3143
$value = $all[0]->getValue();
44+
45+
assert(Repository::create()->getAll() === []);
46+
47+
$all2 = Repository::create()->getAll();
48+
$value2 = $all2[0]->getValue();
49+
50+
function testImpureArgument(Repository $repository): void {
51+
assert($repository->getAllFor(Repository::create()) === []);
52+
53+
$all = $repository->getAllFor(Repository::create());
54+
$value = $all[0]->getValue();
55+
}

0 commit comments

Comments
 (0)