Skip to content

Commit c926144

Browse files
committed
Fix type aliases in method-level template types
1 parent e5e48ea commit c926144

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

src/Type/FileTypeMapper.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,12 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
304304
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
305305
$phpDocString = GetLastDocComment::forNode($node);
306306
if ($phpDocString !== null) {
307-
$typeMapStack[] = function () use ($namespace, $uses, $className, $functionName, $phpDocString, $typeMapStack, $constUses): TemplateTypeMap {
307+
$typeMapStack[] = function () use ($namespace, $uses, $className, $functionName, $phpDocString, $typeMapStack, $typeAliasStack, $constUses): TemplateTypeMap {
308308
$phpDocNode = $this->resolvePhpDocStringToDocNode($phpDocString);
309309
$typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null;
310310
$currentTypeMap = $typeMapCb !== null ? $typeMapCb() : null;
311-
$nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, [], false, $constUses);
311+
$typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? [];
312+
$nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, $typeAliasesMap, false, $constUses);
312313
$templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope);
313314
$templateTypeScope = $nameScope->getTemplateTypeScope();
314315
if ($templateTypeScope === null) {

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,12 @@ public function testBug8983(): void
11641164
$this->assertNoErrors($errors);
11651165
}
11661166

1167+
public function testBug9008(): void
1168+
{
1169+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9008.php');
1170+
$this->assertNoErrors($errors);
1171+
}
1172+
11671173
/**
11681174
* @param string[]|null $allAnalysedFiles
11691175
* @return Error[]
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Bug9008;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class A {}
8+
class B {}
9+
class C {}
10+
11+
/** @phpstan-type Alpha A|B|C */
12+
class Example
13+
{
14+
/**
15+
* @template TypeAlpha of Alpha
16+
* @param TypeAlpha $alpha
17+
* @phpstan-return TypeAlpha
18+
*/
19+
public function shouldWorkOne(object $alpha): object
20+
{
21+
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::shouldWorkOne(), argument)', $alpha);
22+
return $alpha;
23+
}
24+
25+
/**
26+
* @template TypeAlpha of Alpha
27+
* @param TypeAlpha $alpha
28+
* @phpstan-return TypeAlpha
29+
*/
30+
public function shouldWorkTwo(object $alpha): object
31+
{
32+
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::shouldWorkTwo(), argument)', $alpha);
33+
return $alpha;
34+
}
35+
36+
/**
37+
* @template TypeAlpha of A|B|C
38+
* @param TypeAlpha $alpha
39+
* @phpstan-return TypeAlpha
40+
*/
41+
public function worksButExtraVerboseOne(object $alpha): object
42+
{
43+
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::worksButExtraVerboseOne(), argument)', $alpha);
44+
return $alpha;
45+
}
46+
47+
/**
48+
* @template TypeAlpha of A|B|C
49+
* @param TypeAlpha $alpha
50+
* @phpstan-return TypeAlpha
51+
*/
52+
public function worksButExtraVerboseTwo(object $alpha): object
53+
{
54+
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::worksButExtraVerboseTwo(), argument)', $alpha);
55+
return $alpha;
56+
}
57+
58+
/**
59+
* @param Alpha $alpha
60+
*/
61+
public function test(object $alpha): void
62+
{
63+
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $alpha);
64+
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->shouldWorkOne($alpha));
65+
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->shouldWorkTwo($alpha));
66+
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->worksButExtraVerboseOne($alpha));
67+
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->worksButExtraVerboseTwo($alpha));
68+
}
69+
}

0 commit comments

Comments
 (0)