Skip to content

Commit 2a94edb

Browse files
authored
Merge branch refs/heads/1.12.x into 2.1.x
2 parents 150b2e2 + c126d48 commit 2a94edb

File tree

2 files changed

+58
-41
lines changed

2 files changed

+58
-41
lines changed

src/Type/Generic/GenericStaticType.php

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -86,65 +86,59 @@ public function changeBaseClass(ClassReflection $classReflection): StaticType
8686
return new StaticType($classReflection);
8787
}
8888

89-
// this template type mapping logic is very similar to mapping logic in MutatingScope::exactInstantiation()
90-
// where inferring "new Foo" but with the constructor being only in Foo parent class
89+
$templateTags = $this->getClassReflection()->getTemplateTags();
90+
$i = 0;
91+
$indexedTypes = [];
92+
$indexedVariances = [];
93+
foreach ($templateTags as $typeName => $tag) {
94+
if (!array_key_exists($i, $this->types)) {
95+
break;
96+
}
97+
if (!array_key_exists($i, $this->variances)) {
98+
break;
99+
}
100+
$indexedTypes[$typeName] = $this->types[$i];
101+
$indexedVariances[$typeName] = $this->variances[$i];
102+
$i++;
103+
}
91104

92105
$newType = new GenericObjectType($classReflection->getName(), $classReflection->typeMapToList($classReflection->getTemplateTypeMap()));
93106
$ancestorType = $newType->getAncestorWithClassName($this->getClassName());
94107
if ($ancestorType === null) {
95-
return new self($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), $this->subtractedType, $this->variances);
108+
return new self(
109+
$classReflection,
110+
$classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()),
111+
$this->subtractedType,
112+
$classReflection->varianceMapToList($classReflection->getCallSiteVarianceMap()),
113+
);
96114
}
97115

98-
$ancestorClassReflections = $ancestorType->getObjectClassReflections();
99-
if (count($ancestorClassReflections) !== 1) {
100-
return new self($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), $this->subtractedType, $this->variances);
116+
$ancestorClassReflection = $ancestorType->getClassReflection();
117+
if ($ancestorClassReflection === null) {
118+
return new self(
119+
$classReflection,
120+
$classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()),
121+
$this->subtractedType,
122+
$classReflection->varianceMapToList($classReflection->getCallSiteVarianceMap()),
123+
);
101124
}
102125

103-
$ancestorClassReflection = $ancestorClassReflections[0];
104-
$ancestorMapping = [];
126+
$newClassTypes = [];
127+
$newClassVariances = [];
105128
foreach ($ancestorClassReflection->getActiveTemplateTypeMap()->getTypes() as $typeName => $templateType) {
106129
if (!$templateType instanceof TemplateType) {
107130
continue;
108131
}
109132

110-
$ancestorMapping[$typeName] = $templateType;
111-
}
112-
113-
$resolvedTypeMap = [];
114-
foreach ($ancestorClassReflection->typeMapFromList($this->types)->getTypes() as $typeName => $type) {
115-
if (!array_key_exists($typeName, $ancestorMapping)) {
116-
continue;
117-
}
118-
119-
$ancestorType = $ancestorMapping[$typeName];
120-
if (!$ancestorType->getBound()->isSuperTypeOf($type)->yes()) {
121-
continue;
122-
}
123-
124-
if (!array_key_exists($ancestorType->getName(), $resolvedTypeMap)) {
125-
$resolvedTypeMap[$ancestorType->getName()] = $type;
126-
continue;
127-
}
128-
129-
$resolvedTypeMap[$ancestorType->getName()] = TypeCombinator::union($resolvedTypeMap[$ancestorType->getName()], $type);
130-
}
131-
132-
$resolvedVariances = [];
133-
foreach ($ancestorClassReflection->varianceMapFromList($this->variances)->getVariances() as $typeName => $variance) {
134-
if (!array_key_exists($typeName, $ancestorMapping)) {
135-
continue;
136-
}
137-
138-
$ancestorType = $ancestorMapping[$typeName];
139-
if (!array_key_exists($ancestorType->getName(), $resolvedVariances)) {
140-
$resolvedVariances[$ancestorType->getName()] = $variance;
133+
if (!array_key_exists($typeName, $indexedTypes)) {
141134
continue;
142135
}
143136

144-
$resolvedVariances[$ancestorType->getName()] = $resolvedVariances[$ancestorType->getName()]->compose($variance);
137+
$newClassTypes[$templateType->getName()] = $indexedTypes[$typeName];
138+
$newClassVariances[$templateType->getName()] = $indexedVariances[$typeName];
145139
}
146140

147-
return new self($classReflection, $classReflection->typeMapToList(new TemplateTypeMap($resolvedTypeMap)), $this->subtractedType, $classReflection->varianceMapToList(new TemplateTypeVarianceMap($resolvedVariances)));
141+
return new self($classReflection, $classReflection->typeMapToList(new TemplateTypeMap($newClassTypes)), $this->subtractedType, $classReflection->varianceMapToList(new TemplateTypeVarianceMap($newClassVariances)));
148142
}
149143

150144
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult

tests/PHPStan/Analyser/nsrt/generic-static.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,29 @@ public function test(self $s): void
126126

127127
}
128128

129+
/**
130+
* @template T
131+
* @implements Foo<T, float>
132+
*/
133+
abstract class Inconsistent3 implements Foo
134+
{
135+
136+
public function fluent()
137+
{
138+
139+
}
140+
141+
/**
142+
* @param Inconsistent3<int> $s
143+
*/
144+
public function test(self $s): void
145+
{
146+
assertType('static(GenericStatic\Inconsistent3<T (class GenericStatic\Inconsistent3, argument)>)', $this->fluent());
147+
assertType('GenericStatic\\Inconsistent3<int>', $s->fluent());
148+
}
149+
150+
}
151+
129152
/**
130153
* @template T
131154
* @template K

0 commit comments

Comments
 (0)