@@ -1146,7 +1146,7 @@ class ReturnInfo {
11461146 self ::REFCOUNT_N ,
11471147 ];
11481148
1149- public /* readonly */ bool $ byRef ;
1149+ private /* readonly */ bool $ byRef ;
11501150 // NOT readonly - gets removed when discarding info for older PHP versions
11511151 public ?Type $ type ;
11521152 public /* readonly */ ?Type $ phpDocType ;
@@ -1193,6 +1193,69 @@ private function setRefcount(?string $refcount): void
11931193
11941194 $ this ->refcount = $ refcount ;
11951195 }
1196+
1197+ public function beginArgInfo (string $ funcInfoName , int $ minArgs , bool $ php81MinimumCompatibility ): string {
1198+ $ code = $ this ->beginArgInfoCompatible ($ funcInfoName , $ minArgs );
1199+ if ($ this ->type !== null && $ this ->tentativeReturnType && !$ php81MinimumCompatibility ) {
1200+ $ realCode = "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ") \n" ;
1201+ $ realCode .= $ code ;
1202+ $ realCode .= sprintf (
1203+ "#else \nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n#endif \n" ,
1204+ $ funcInfoName , $ this ->byRef , $ minArgs
1205+ );
1206+ return $ realCode ;
1207+ }
1208+ return $ code ;
1209+ }
1210+
1211+ /**
1212+ * Assumes PHP 8.1 compatibility, if that is not the case the caller is
1213+ * responsible for making the use of a tentative return type conditional
1214+ * based on the PHP version. Separate to allow using early returns
1215+ */
1216+ private function beginArgInfoCompatible (string $ funcInfoName , int $ minArgs ): string {
1217+ if ($ this ->type !== null ) {
1218+ if (null !== $ simpleReturnType = $ this ->type ->tryToSimpleType ()) {
1219+ if ($ simpleReturnType ->isBuiltin ) {
1220+ return sprintf (
1221+ "%s(%s, %d, %d, %s, %d) \n" ,
1222+ $ this ->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX " ,
1223+ $ funcInfoName , $ this ->byRef ,
1224+ $ minArgs ,
1225+ $ simpleReturnType ->toTypeCode (), $ this ->type ->isNullable ()
1226+ );
1227+ }
1228+ return sprintf (
1229+ "%s(%s, %d, %d, %s, %d) \n" ,
1230+ $ this ->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX " ,
1231+ $ funcInfoName , $ this ->byRef ,
1232+ $ minArgs ,
1233+ $ simpleReturnType ->toEscapedName (), $ this ->type ->isNullable ()
1234+ );
1235+ }
1236+ $ arginfoType = $ this ->type ->toArginfoType ();
1237+ if ($ arginfoType ->hasClassType ()) {
1238+ return sprintf (
1239+ "%s(%s, %d, %d, %s, %s) \n" ,
1240+ $ this ->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX " ,
1241+ $ funcInfoName , $ this ->byRef ,
1242+ $ minArgs ,
1243+ $ arginfoType ->toClassTypeString (), $ arginfoType ->toTypeMask ()
1244+ );
1245+ }
1246+ return sprintf (
1247+ "%s(%s, %d, %d, %s) \n" ,
1248+ $ this ->tentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX " ,
1249+ $ funcInfoName , $ this ->byRef ,
1250+ $ minArgs ,
1251+ $ arginfoType ->toTypeMask ()
1252+ );
1253+ }
1254+ return sprintf (
1255+ "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n" ,
1256+ $ funcInfoName , $ this ->byRef , $ minArgs
1257+ );
1258+ }
11961259}
11971260
11981261class FuncInfo {
@@ -5012,65 +5075,11 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string {
50125075}
50135076
50145077function funcInfoToCode (FileInfo $ fileInfo , FuncInfo $ funcInfo ): string {
5015- $ code = '' ;
5016- $ returnType = $ funcInfo ->return ->type ;
5017- $ isTentativeReturnType = $ funcInfo ->return ->tentativeReturnType ;
5018- $ php81MinimumCompatibility = $ fileInfo ->getMinimumPhpVersionIdCompatibility () === null || $ fileInfo ->getMinimumPhpVersionIdCompatibility () >= PHP_81_VERSION_ID ;
5019-
5020- if ($ returnType !== null ) {
5021- if ($ isTentativeReturnType && !$ php81MinimumCompatibility ) {
5022- $ code .= "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ") \n" ;
5023- }
5024- if (null !== $ simpleReturnType = $ returnType ->tryToSimpleType ()) {
5025- if ($ simpleReturnType ->isBuiltin ) {
5026- $ code .= sprintf (
5027- "%s(%s, %d, %d, %s, %d) \n" ,
5028- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX " ,
5029- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5030- $ funcInfo ->numRequiredArgs ,
5031- $ simpleReturnType ->toTypeCode (), $ returnType ->isNullable ()
5032- );
5033- } else {
5034- $ code .= sprintf (
5035- "%s(%s, %d, %d, %s, %d) \n" ,
5036- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX " ,
5037- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5038- $ funcInfo ->numRequiredArgs ,
5039- $ simpleReturnType ->toEscapedName (), $ returnType ->isNullable ()
5040- );
5041- }
5042- } else {
5043- $ arginfoType = $ returnType ->toArginfoType ();
5044- if ($ arginfoType ->hasClassType ()) {
5045- $ code .= sprintf (
5046- "%s(%s, %d, %d, %s, %s) \n" ,
5047- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX " ,
5048- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5049- $ funcInfo ->numRequiredArgs ,
5050- $ arginfoType ->toClassTypeString (), $ arginfoType ->toTypeMask ()
5051- );
5052- } else {
5053- $ code .= sprintf (
5054- "%s(%s, %d, %d, %s) \n" ,
5055- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX " ,
5056- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5057- $ funcInfo ->numRequiredArgs ,
5058- $ arginfoType ->toTypeMask ()
5059- );
5060- }
5061- }
5062- if ($ isTentativeReturnType && !$ php81MinimumCompatibility ) {
5063- $ code .= sprintf (
5064- "#else \nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n#endif \n" ,
5065- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef , $ funcInfo ->numRequiredArgs
5066- );
5067- }
5068- } else {
5069- $ code .= sprintf (
5070- "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n" ,
5071- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef , $ funcInfo ->numRequiredArgs
5072- );
5073- }
5078+ $ code = $ funcInfo ->return ->beginArgInfo (
5079+ $ funcInfo ->getArgInfoName (),
5080+ $ funcInfo ->numRequiredArgs ,
5081+ $ fileInfo ->getMinimumPhpVersionIdCompatibility () === null || $ fileInfo ->getMinimumPhpVersionIdCompatibility () >= PHP_81_VERSION_ID
5082+ );
50745083
50755084 foreach ($ funcInfo ->args as $ argInfo ) {
50765085 $ code .= $ argInfo ->toZendInfo ();
0 commit comments