Skip to content

Commit 48aea56

Browse files
committed
Nested generic type - correctly infer template types
1 parent e4331af commit 48aea56

File tree

5 files changed

+48
-5
lines changed

5 files changed

+48
-5
lines changed

src/Type/Generic/TemplateTypeTrait.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,15 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
158158
]);
159159
}
160160

161-
$resolvedBound = TemplateTypeHelper::resolveToBounds($this->getBound());
161+
$map = $this->getBound()->inferTemplateTypes($receivedType);
162+
$resolvedBound = TemplateTypeHelper::resolveTemplateTypes($this->getBound(), $map);
162163
if ($resolvedBound->isSuperTypeOf($receivedType)->yes()) {
163164
return (new TemplateTypeMap([
164165
$this->name => $this->shouldGeneralizeInferredType() ? TemplateTypeHelper::generalizeType($receivedType) : $receivedType,
165-
]))->union($this->getBound()->inferTemplateTypes($receivedType));
166+
]))->union($map);
166167
}
167168

168-
return $this->getBound()->inferTemplateTypes($receivedType);
169+
return $map;
169170
}
170171

171172
public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10961,6 +10961,11 @@ public function dataIteratorIterator(): array
1096110961
return $this->gatherAssertTypes(__DIR__ . '/data/iterator-iterator.php');
1096210962
}
1096310963

10964+
public function dataBug4642(): array
10965+
{
10966+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4642.php');
10967+
}
10968+
1096410969
/**
1096510970
* @param string $file
1096610971
* @return array<string, mixed[]>
@@ -11214,6 +11219,7 @@ private function gatherAssertTypes(string $file): array
1121411219
* @dataProvider dataNestedGenericTypesUnwrapping
1121511220
* @dataProvider dataNestedGenericIncompleteConstructor
1121611221
* @dataProvider dataIteratorIterator
11222+
* @dataProvider dataBug4642
1121711223
* @param string $assertType
1121811224
* @param string $file
1121911225
* @param mixed ...$args
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Bug4642;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
interface IEntity {}
8+
/** @template E of IEntity */
9+
interface IRepository {}
10+
11+
interface I {
12+
/**
13+
* Returns repository by repository class.
14+
* @template E of IEntity
15+
* @template T of IRepository<E>
16+
* @phpstan-param class-string<T> $className
17+
* @phpstan-return T
18+
*/
19+
function getRepository(string $className): IRepository;
20+
}
21+
22+
class User implements IEntity {}
23+
/** @implements IRepository<User> */
24+
class UsersRepository implements IRepository {}
25+
26+
function (I $model): void {
27+
assertType(UsersRepository::class, $model->getRepository(UsersRepository::class));
28+
};

tests/PHPStan/Analyser/data/nested-generic-types-unwrapping.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ function (): void {
103103

104104
function (): void {
105105
$result = loadWithIndirectUnwrap2(SomePackage::class);
106-
assertType('NestedGenericTypesUnwrapping\GenericPackage<NestedGenericTypesUnwrapping\SomeInnerPackage>', $result);
106+
assertType(SomePackage::class, $result);
107107
};
108108

109109
function (SomePackage $somePackage): void {
110110
$result = unwrapGeneric($somePackage);
111111
assertType(SomeInnerPackage::class, $result);
112112

113113
$result = unwrapGeneric2($somePackage);
114-
assertType('NestedGenericTypesUnwrapping\GenericPackage<NestedGenericTypesUnwrapping\SomeInnerPackage>', $result);
114+
assertType(SomePackage::class, $result);
115115
};

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,4 +1883,12 @@ public function testBug3922(): void
18831883
]);
18841884
}
18851885

1886+
public function testBug4642(): void
1887+
{
1888+
$this->checkThisOnly = false;
1889+
$this->checkNullables = true;
1890+
$this->checkUnionTypes = true;
1891+
$this->analyse([__DIR__ . '/../../Analyser/data/bug-4642.php'], []);
1892+
}
1893+
18861894
}

0 commit comments

Comments
 (0)