@@ -318,6 +318,53 @@ static inline bool can_elide_return_type_check(
318318 return false;
319319}
320320
321+ static inline bool can_return_value_safely_be_coerced (
322+ const zend_op_array * op_array , const zend_ssa * ssa , const zend_ssa_op * ssa_op , zend_op * opline
323+ ) {
324+ const uint32_t return_type_mask = ZEND_TYPE_FULL_MASK (op_array -> arg_info [-1 ].type );
325+ const zend_ssa_var_info * use_info = & ssa -> var_info [ssa_op -> op1_use ];
326+
327+ /* Type preference order: int -> float -> string -> bool */
328+ /* Can always safely cast booleans to inter */
329+ if (return_type_mask & MAY_BE_LONG ) {
330+ if (use_info -> type & MAY_BE_BOOL ) {
331+ opline -> opcode = ZEND_CAST ;
332+ opline -> extended_value = IS_LONG ;
333+ return true;
334+ }
335+ return false;
336+ }
337+ if (return_type_mask & MAY_BE_DOUBLE ) {
338+ /* Can always safely cast booleans, and integers to float */
339+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_BOOL )) {
340+ opline -> opcode = ZEND_CAST ;
341+ opline -> extended_value = IS_DOUBLE ;
342+ return true;
343+ }
344+ return false;
345+ }
346+ /* Can always safely cast booleans, and integers to string,
347+ * float value must not be NAN */
348+ if (return_type_mask & MAY_BE_STRING ) {
349+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_BOOL )) {
350+ opline -> opcode = ZEND_CAST ;
351+ opline -> extended_value = IS_STRING ;
352+ return true;
353+ }
354+ return false;
355+ }
356+ return false;
357+ if ((return_type_mask & MAY_BE_BOOL ) == MAY_BE_BOOL ) {
358+ /* Can always safely cast integers and strings to bool,
359+ * float value must not be NAN */
360+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_STRING )) {
361+ opline -> opcode = ZEND_BOOL ;
362+ return true;
363+ }
364+ return false;
365+ }
366+ }
367+
321368static bool opline_supports_assign_contraction (
322369 zend_op_array * op_array , zend_ssa * ssa , zend_op * opline , int src_var , uint32_t cv_var ) {
323370 if (opline -> opcode == ZEND_NEW ) {
@@ -1289,6 +1336,8 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
12891336
12901337 MAKE_NOP (opline );
12911338 remove_nops = 1 ;
1339+ } else if (can_return_value_safely_be_coerced (op_array , ssa , & ssa -> ops [op_1 ], opline )) {
1340+ continue ;
12921341 }
12931342 }
12941343 }
0 commit comments