@@ -222,6 +222,29 @@ class CalledOnTypeUnresolvedMethodPrototypeReflection
222222 }
223223 zv::Val staticObjectType = pt_type_call (Z_OBJ_P (changed.raw ()), PT_LC (" getstaticobjecttype" ), 0 , NULL );
224224 if (UNEXPECTED (staticObjectType.isUndef ())) return ;
225+ /* a GenericObjectType is rebuilt without the class reflection of the
226+ * declaring class, which would not know the resolved type arguments:
227+ * new GenericObjectType($t->getClassName(), $t->getTypes(), $t->getSubtractedType(), variances: $t->getVariances()) */
228+ bool isGenericObject;
229+ pt_type_instanceof_ce (staticObjectType.raw (), pt_ce_generic_object_type, isGenericObject);
230+ if (isGenericObject) {
231+ zend_object *objectType = Z_OBJ_P (staticObjectType.raw ());
232+ zv::Val className = pt_type_call (objectType, PT_LC (" getclassname" ), 0 , NULL );
233+ if (UNEXPECTED (className.isUndef ())) return ;
234+ zv::Val objectTypes = pt_type_call (objectType, PT_LC (" gettypes" ), 0 , NULL );
235+ if (UNEXPECTED (objectTypes.isUndef ())) return ;
236+ zv::Val subtracted = pt_type_call (objectType, PT_LC (" getsubtractedtype" ), 0 , NULL );
237+ if (UNEXPECTED (subtracted.isUndef ())) return ;
238+ zv::Val objectVariances = pt_type_call (objectType, PT_LC (" getvariances" ), 0 , NULL );
239+ if (UNEXPECTED (objectVariances.isUndef ())) return ;
240+ if (UNEXPECTED (Z_TYPE_P (className.raw ()) != IS_STRING )) {
241+ zend_type_error (" phpstan_turbo: getClassName() must return a string" );
242+ return ;
243+ }
244+ zval rebuiltRaw;
245+ if (UNEXPECTED (!pt_generic_object_type_new (&rebuiltRaw, Z_STR_P (className.raw ()), objectTypes.raw (), subtracted.raw (), NULL , objectVariances.raw ()))) return ;
246+ staticObjectType = zv::Val::adopt (rebuiltRaw);
247+ }
225248 zv::Val traversed = pt_type_call_callable (&argv[1 ], 1 , staticObjectType.raw ());
226249 if (UNEXPECTED (traversed.isUndef ())) return ;
227250 traversed.intoReturnValue (return_value);
0 commit comments