Skip to content

Commit

Permalink
Fix type aliases in method-level template types
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 7, 2023
1 parent e5e48ea commit c926144
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/Type/FileTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,12 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
$phpDocString = GetLastDocComment::forNode($node);
if ($phpDocString !== null) {
$typeMapStack[] = function () use ($namespace, $uses, $className, $functionName, $phpDocString, $typeMapStack, $constUses): TemplateTypeMap {
$typeMapStack[] = function () use ($namespace, $uses, $className, $functionName, $phpDocString, $typeMapStack, $typeAliasStack, $constUses): TemplateTypeMap {
$phpDocNode = $this->resolvePhpDocStringToDocNode($phpDocString);
$typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null;
$currentTypeMap = $typeMapCb !== null ? $typeMapCb() : null;
$nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, [], false, $constUses);
$typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? [];
$nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, $typeAliasesMap, false, $constUses);
$templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope);
$templateTypeScope = $nameScope->getTemplateTypeScope();
if ($templateTypeScope === null) {
Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,12 @@ public function testBug8983(): void
$this->assertNoErrors($errors);
}

public function testBug9008(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9008.php');
$this->assertNoErrors($errors);
}

/**
* @param string[]|null $allAnalysedFiles
* @return Error[]
Expand Down
69 changes: 69 additions & 0 deletions tests/PHPStan/Analyser/data/bug-9008.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Bug9008;

use function PHPStan\Testing\assertType;

class A {}
class B {}
class C {}

/** @phpstan-type Alpha A|B|C */
class Example
{
/**
* @template TypeAlpha of Alpha
* @param TypeAlpha $alpha
* @phpstan-return TypeAlpha
*/
public function shouldWorkOne(object $alpha): object
{
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::shouldWorkOne(), argument)', $alpha);
return $alpha;
}

/**
* @template TypeAlpha of Alpha
* @param TypeAlpha $alpha
* @phpstan-return TypeAlpha
*/
public function shouldWorkTwo(object $alpha): object
{
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::shouldWorkTwo(), argument)', $alpha);
return $alpha;
}

/**
* @template TypeAlpha of A|B|C
* @param TypeAlpha $alpha
* @phpstan-return TypeAlpha
*/
public function worksButExtraVerboseOne(object $alpha): object
{
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::worksButExtraVerboseOne(), argument)', $alpha);
return $alpha;
}

/**
* @template TypeAlpha of A|B|C
* @param TypeAlpha $alpha
* @phpstan-return TypeAlpha
*/
public function worksButExtraVerboseTwo(object $alpha): object
{
assertType('TypeAlpha of Bug9008\A|Bug9008\B|Bug9008\C (method Bug9008\Example::worksButExtraVerboseTwo(), argument)', $alpha);
return $alpha;
}

/**
* @param Alpha $alpha
*/
public function test(object $alpha): void
{
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $alpha);
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->shouldWorkOne($alpha));
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->shouldWorkTwo($alpha));
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->worksButExtraVerboseOne($alpha));
assertType('Bug9008\\A|Bug9008\\B|Bug9008\\C', $this->worksButExtraVerboseTwo($alpha));
}
}

0 comments on commit c926144

Please sign in to comment.