@@ -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 {
@@ -4985,65 +5048,11 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string {
49855048}
49865049
49875050function funcInfoToCode (FileInfo $ fileInfo , FuncInfo $ funcInfo ): string {
4988- $ code = '' ;
4989- $ returnType = $ funcInfo ->return ->type ;
4990- $ isTentativeReturnType = $ funcInfo ->return ->tentativeReturnType ;
4991- $ php81MinimumCompatibility = $ fileInfo ->getMinimumPhpVersionIdCompatibility () === null || $ fileInfo ->getMinimumPhpVersionIdCompatibility () >= PHP_81_VERSION_ID ;
4992-
4993- if ($ returnType !== null ) {
4994- if ($ isTentativeReturnType && !$ php81MinimumCompatibility ) {
4995- $ code .= "#if (PHP_VERSION_ID >= " . PHP_81_VERSION_ID . ") \n" ;
4996- }
4997- if (null !== $ simpleReturnType = $ returnType ->tryToSimpleType ()) {
4998- if ($ simpleReturnType ->isBuiltin ) {
4999- $ code .= sprintf (
5000- "%s(%s, %d, %d, %s, %d) \n" ,
5001- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX " ,
5002- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5003- $ funcInfo ->numRequiredArgs ,
5004- $ simpleReturnType ->toTypeCode (), $ returnType ->isNullable ()
5005- );
5006- } else {
5007- $ code .= sprintf (
5008- "%s(%s, %d, %d, %s, %d) \n" ,
5009- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX " ,
5010- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5011- $ funcInfo ->numRequiredArgs ,
5012- $ simpleReturnType ->toEscapedName (), $ returnType ->isNullable ()
5013- );
5014- }
5015- } else {
5016- $ arginfoType = $ returnType ->toArginfoType ();
5017- if ($ arginfoType ->hasClassType ()) {
5018- $ code .= sprintf (
5019- "%s(%s, %d, %d, %s, %s) \n" ,
5020- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX " ,
5021- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5022- $ funcInfo ->numRequiredArgs ,
5023- $ arginfoType ->toClassTypeString (), $ arginfoType ->toTypeMask ()
5024- );
5025- } else {
5026- $ code .= sprintf (
5027- "%s(%s, %d, %d, %s) \n" ,
5028- $ isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX " : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX " ,
5029- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef ,
5030- $ funcInfo ->numRequiredArgs ,
5031- $ arginfoType ->toTypeMask ()
5032- );
5033- }
5034- }
5035- if ($ isTentativeReturnType && !$ php81MinimumCompatibility ) {
5036- $ code .= sprintf (
5037- "#else \nZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n#endif \n" ,
5038- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef , $ funcInfo ->numRequiredArgs
5039- );
5040- }
5041- } else {
5042- $ code .= sprintf (
5043- "ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d) \n" ,
5044- $ funcInfo ->getArgInfoName (), $ funcInfo ->return ->byRef , $ funcInfo ->numRequiredArgs
5045- );
5046- }
5051+ $ code = $ funcInfo ->return ->beginArgInfo (
5052+ $ funcInfo ->getArgInfoName (),
5053+ $ funcInfo ->numRequiredArgs ,
5054+ $ fileInfo ->getMinimumPhpVersionIdCompatibility () === null || $ fileInfo ->getMinimumPhpVersionIdCompatibility () >= PHP_81_VERSION_ID
5055+ );
50475056
50485057 foreach ($ funcInfo ->args as $ argInfo ) {
50495058 $ code .= $ argInfo ->toZendInfo ();
0 commit comments