@@ -96,65 +96,59 @@ public function changeBaseClass(ClassReflection $classReflection): StaticType
96
96
return new StaticType ($ classReflection );
97
97
}
98
98
99
- // this template type mapping logic is very similar to mapping logic in MutatingScope::exactInstantiation()
100
- // where inferring "new Foo" but with the constructor being only in Foo parent class
99
+ $ templateTags = $ this ->getClassReflection ()->getTemplateTags ();
100
+ $ i = 0 ;
101
+ $ indexedTypes = [];
102
+ $ indexedVariances = [];
103
+ foreach ($ templateTags as $ typeName => $ tag ) {
104
+ if (!array_key_exists ($ i , $ this ->types )) {
105
+ break ;
106
+ }
107
+ if (!array_key_exists ($ i , $ this ->variances )) {
108
+ break ;
109
+ }
110
+ $ indexedTypes [$ typeName ] = $ this ->types [$ i ];
111
+ $ indexedVariances [$ typeName ] = $ this ->variances [$ i ];
112
+ $ i ++;
113
+ }
101
114
102
115
$ newType = new GenericObjectType ($ classReflection ->getName (), $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()));
103
116
$ ancestorType = $ newType ->getAncestorWithClassName ($ this ->getClassName ());
104
117
if ($ ancestorType === null ) {
105
- return new self ($ classReflection , $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()->resolveToBounds ()), $ this ->subtractedType , $ this ->variances );
118
+ return new self (
119
+ $ classReflection ,
120
+ $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()->resolveToBounds ()),
121
+ $ this ->subtractedType ,
122
+ $ classReflection ->varianceMapToList ($ classReflection ->getCallSiteVarianceMap ()),
123
+ );
106
124
}
107
125
108
- $ ancestorClassReflections = $ ancestorType ->getObjectClassReflections ();
109
- if (count ($ ancestorClassReflections ) !== 1 ) {
110
- return new self ($ classReflection , $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()->resolveToBounds ()), $ this ->subtractedType , $ this ->variances );
126
+ $ ancestorClassReflection = $ ancestorType ->getClassReflection ();
127
+ if ($ ancestorClassReflection === null ) {
128
+ return new self (
129
+ $ classReflection ,
130
+ $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()->resolveToBounds ()),
131
+ $ this ->subtractedType ,
132
+ $ classReflection ->varianceMapToList ($ classReflection ->getCallSiteVarianceMap ()),
133
+ );
111
134
}
112
135
113
- $ ancestorClassReflection = $ ancestorClassReflections [ 0 ];
114
- $ ancestorMapping = [];
136
+ $ newClassTypes = [ ];
137
+ $ newClassVariances = [];
115
138
foreach ($ ancestorClassReflection ->getActiveTemplateTypeMap ()->getTypes () as $ typeName => $ templateType ) {
116
139
if (!$ templateType instanceof TemplateType) {
117
140
continue ;
118
141
}
119
142
120
- $ ancestorMapping [$ typeName ] = $ templateType ;
121
- }
122
-
123
- $ resolvedTypeMap = [];
124
- foreach ($ ancestorClassReflection ->typeMapFromList ($ this ->types )->getTypes () as $ typeName => $ type ) {
125
- if (!array_key_exists ($ typeName , $ ancestorMapping )) {
126
- continue ;
127
- }
128
-
129
- $ ancestorType = $ ancestorMapping [$ typeName ];
130
- if (!$ ancestorType ->getBound ()->isSuperTypeOf ($ type )->yes ()) {
131
- continue ;
132
- }
133
-
134
- if (!array_key_exists ($ ancestorType ->getName (), $ resolvedTypeMap )) {
135
- $ resolvedTypeMap [$ ancestorType ->getName ()] = $ type ;
136
- continue ;
137
- }
138
-
139
- $ resolvedTypeMap [$ ancestorType ->getName ()] = TypeCombinator::union ($ resolvedTypeMap [$ ancestorType ->getName ()], $ type );
140
- }
141
-
142
- $ resolvedVariances = [];
143
- foreach ($ ancestorClassReflection ->varianceMapFromList ($ this ->variances )->getVariances () as $ typeName => $ variance ) {
144
- if (!array_key_exists ($ typeName , $ ancestorMapping )) {
145
- continue ;
146
- }
147
-
148
- $ ancestorType = $ ancestorMapping [$ typeName ];
149
- if (!array_key_exists ($ ancestorType ->getName (), $ resolvedVariances )) {
150
- $ resolvedVariances [$ ancestorType ->getName ()] = $ variance ;
143
+ if (!array_key_exists ($ typeName , $ indexedTypes )) {
151
144
continue ;
152
145
}
153
146
154
- $ resolvedVariances [$ ancestorType ->getName ()] = $ resolvedVariances [$ ancestorType ->getName ()]->compose ($ variance );
147
+ $ newClassTypes [$ templateType ->getName ()] = $ indexedTypes [$ typeName ];
148
+ $ newClassVariances [$ templateType ->getName ()] = $ indexedVariances [$ typeName ];
155
149
}
156
150
157
- return new self ($ classReflection , $ classReflection ->typeMapToList (new TemplateTypeMap ($ resolvedTypeMap )), $ this ->subtractedType , $ classReflection ->varianceMapToList (new TemplateTypeVarianceMap ($ resolvedVariances )));
151
+ return new self ($ classReflection , $ classReflection ->typeMapToList (new TemplateTypeMap ($ newClassTypes )), $ this ->subtractedType , $ classReflection ->varianceMapToList (new TemplateTypeVarianceMap ($ newClassVariances )));
158
152
}
159
153
160
154
public function isSuperTypeOfWithReason (Type $ type ): IsSuperTypeOfResult
0 commit comments