Skip to content

Commit b8f8a71

Browse files
committed
Regression test
Closes phpstan/phpstan#3321
1 parent 78a9f05 commit b8f8a71

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10902,6 +10902,11 @@ public function dataBug4579(): array
1090210902
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4579.php');
1090310903
}
1090410904

10905+
public function dataBug3321(): array
10906+
{
10907+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3321.php');
10908+
}
10909+
1090510910
/**
1090610911
* @param string $file
1090710912
* @return array<string, mixed[]>
@@ -11144,6 +11149,7 @@ private function gatherAssertTypes(string $file): array
1114411149
* @dataProvider dataBug4573
1114511150
* @dataProvider dataBug4577
1114611151
* @dataProvider dataBug4579
11152+
* @dataProvider dataBug3321
1114711153
* @param string $assertType
1114811154
* @param string $file
1114911155
* @param mixed ...$args
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Bug3321;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
/** @template T */
8+
interface Container {
9+
/** @return T */
10+
public function get();
11+
}
12+
13+
14+
class Foo
15+
{
16+
17+
/**
18+
* @template T
19+
* @param array<Container<T>> $containers
20+
* @return T
21+
*/
22+
function unwrap(array $containers) {
23+
return array_map(
24+
function ($container) {
25+
return $container->get();
26+
},
27+
$containers
28+
)[0];
29+
}
30+
31+
/**
32+
* @param array<Container<int>> $typed_containers
33+
*/
34+
function takesDifferentTypes(array $typed_containers): void {
35+
assertType('int', $this->unwrap($typed_containers));
36+
}
37+
38+
}
39+
40+
/**
41+
* @template TFacade of Facade
42+
*/
43+
interface Facadable
44+
{
45+
}
46+
47+
/**
48+
* @implements Facadable<AFacade>
49+
*/
50+
class A implements Facadable {}
51+
52+
/**
53+
* @implements Facadable<BFacade>
54+
*/
55+
class B implements Facadable {}
56+
57+
abstract class Facade {}
58+
class AFacade extends Facade {}
59+
class BFacade extends Facade {}
60+
61+
class FacadeFactory {
62+
/**
63+
* @template TFacade of Facade
64+
* @param class-string<Facadable<TFacade>> $class
65+
* @return TFacade
66+
*/
67+
public function create(string $class): Facade
68+
{
69+
// Returns facade for class
70+
}
71+
}
72+
73+
74+
function (FacadeFactory $f): void {
75+
$facadeA = $f->create(A::class);
76+
assertType(AFacade::class, $facadeA);
77+
};

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,4 +1854,12 @@ public function testBug4209Two(): void
18541854
$this->analyse([__DIR__ . '/../../Analyser/data/bug-4209-2.php'], []);
18551855
}
18561856

1857+
public function testBug3321(): void
1858+
{
1859+
$this->checkThisOnly = false;
1860+
$this->checkNullables = true;
1861+
$this->checkUnionTypes = true;
1862+
$this->analyse([__DIR__ . '/../../Analyser/data/bug-3321.php'], []);
1863+
}
1864+
18571865
}

0 commit comments

Comments
 (0)