@@ -96,65 +96,59 @@ public function changeBaseClass(ClassReflection $classReflection): StaticType
9696 return new StaticType ($ classReflection );
9797 }
9898
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+ }
101114
102115 $ newType = new GenericObjectType ($ classReflection ->getName (), $ classReflection ->typeMapToList ($ classReflection ->getTemplateTypeMap ()));
103116 $ ancestorType = $ newType ->getAncestorWithClassName ($ this ->getClassName ());
104117 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+ );
106124 }
107125
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+ );
111134 }
112135
113- $ ancestorClassReflection = $ ancestorClassReflections [ 0 ];
114- $ ancestorMapping = [];
136+ $ newClassTypes = [ ];
137+ $ newClassVariances = [];
115138 foreach ($ ancestorClassReflection ->getActiveTemplateTypeMap ()->getTypes () as $ typeName => $ templateType ) {
116139 if (!$ templateType instanceof TemplateType) {
117140 continue ;
118141 }
119142
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 )) {
151144 continue ;
152145 }
153146
154- $ resolvedVariances [$ ancestorType ->getName ()] = $ resolvedVariances [$ ancestorType ->getName ()]->compose ($ variance );
147+ $ newClassTypes [$ templateType ->getName ()] = $ indexedTypes [$ typeName ];
148+ $ newClassVariances [$ templateType ->getName ()] = $ indexedVariances [$ typeName ];
155149 }
156150
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 )));
158152 }
159153
160154 public function isSuperTypeOfWithReason (Type $ type ): IsSuperTypeOfResult
0 commit comments