Skip to content

Commit 9d191f9

Browse files
committed
Support bool as template type bound
1 parent 5a44c29 commit 9d191f9

File tree

5 files changed

+84
-0
lines changed

5 files changed

+84
-0
lines changed

src/Rules/Generics/TemplateTypeCheck.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Rules\ClassCaseSensitivityCheck;
88
use PHPStan\Rules\ClassNameNodePair;
99
use PHPStan\Rules\RuleErrorBuilder;
10+
use PHPStan\Type\BooleanType;
1011
use PHPStan\Type\Generic\GenericObjectType;
1112
use PHPStan\Type\Generic\TemplateType;
1213
use PHPStan\Type\Generic\TemplateTypeScope;
@@ -110,6 +111,7 @@ public function check(
110111
$boundClass === MixedType::class
111112
|| $boundClass === StringType::class
112113
|| $boundClass === IntegerType::class
114+
|| $boundClass === BooleanType::class
113115
|| $boundClass === ObjectWithoutClassType::class
114116
|| $boundClass === ObjectType::class
115117
|| $boundClass === GenericObjectType::class
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Generic;
4+
5+
use PHPStan\Type\BooleanType;
6+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
7+
use PHPStan\Type\Type;
8+
9+
/** @api */
10+
final class TemplateBooleanType extends BooleanType implements TemplateType
11+
{
12+
13+
/** @use TemplateTypeTrait<BooleanType> */
14+
use TemplateTypeTrait;
15+
use UndecidedComparisonCompoundTypeTrait;
16+
17+
public function __construct(
18+
TemplateTypeScope $scope,
19+
TemplateTypeStrategy $templateTypeStrategy,
20+
TemplateTypeVariance $templateTypeVariance,
21+
string $name,
22+
BooleanType $bound
23+
)
24+
{
25+
parent::__construct();
26+
$this->scope = $scope;
27+
$this->strategy = $templateTypeStrategy;
28+
$this->variance = $templateTypeVariance;
29+
$this->name = $name;
30+
$this->bound = $bound;
31+
}
32+
33+
public function traverse(callable $cb): Type
34+
{
35+
$newBound = $cb($this->getBound());
36+
if ($this->getBound() !== $newBound && $newBound instanceof BooleanType) {
37+
return new self(
38+
$this->scope,
39+
$this->strategy,
40+
$this->variance,
41+
$this->name,
42+
$newBound
43+
);
44+
}
45+
46+
return $this;
47+
}
48+
49+
protected function shouldGeneralizeInferredType(): bool
50+
{
51+
return false;
52+
}
53+
54+
}

src/Type/Generic/TemplateTypeFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\PhpDoc\Tag\TemplateTag;
66
use PHPStan\Type\BenevolentUnionType;
7+
use PHPStan\Type\BooleanType;
78
use PHPStan\Type\IntegerType;
89
use PHPStan\Type\MixedType;
910
use PHPStan\Type\ObjectType;
@@ -44,6 +45,10 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
4445
return new TemplateIntegerType($scope, $strategy, $variance, $name, $bound);
4546
}
4647

48+
if ($bound instanceof BooleanType && ($boundClass === BooleanType::class || $bound instanceof TemplateType)) {
49+
return new TemplateBooleanType($scope, $strategy, $variance, $name, $bound);
50+
}
51+
4752
if ($bound instanceof MixedType && ($boundClass === MixedType::class || $bound instanceof TemplateType)) {
4853
return new TemplateMixedType($scope, $strategy, $variance, $name, $bound);
4954
}

tests/PHPStan/Analyser/data/generics.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,3 +1405,20 @@ function (): void {
14051405
$array = ['a' => 1, 'b' => 2];
14061406
assertType('array(\'a\' => int, \'b\' => int)', a($array));
14071407
};
1408+
1409+
1410+
/**
1411+
* @template T of bool
1412+
* @param T $b
1413+
* @return T
1414+
*/
1415+
function boolBound(bool $b): bool
1416+
{
1417+
return $b;
1418+
}
1419+
1420+
function (bool $b): void {
1421+
assertType('true', boolBound(true));
1422+
assertType('false', boolBound(false));
1423+
assertType('bool', boolBound($b));
1424+
};

tests/PHPStan/Rules/Generics/data/function-template.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,9 @@ function lorem()
3333
{
3434

3535
}
36+
37+
/** @template T of bool */
38+
function ipsum()
39+
{
40+
41+
}

0 commit comments

Comments
 (0)