Skip to content

Warn when coercing NAN to other types - #19573

Closed
Girgias wants to merge 11 commits into
php:masterfrom
Girgias:8.5-warn-nan-coercion
Closed

Girgias wants to merge 11 commits into
php:masterfrom
Girgias:8.5-warn-nan-coercion

Conversation

@Girgias

@Girgias Girgias commented Aug 24, 2025

Copy link
Copy Markdown
Member

@github-actions

Copy link
Copy Markdown

AWS x86_64 (c7i.24xl)

Attribute Value
Environment aws
Runner host
Instance type c7i.metal-24xl (dedicated)
Architecture x86_64
CPU 48 cores
CPU settings disabled deeper C-states, disabled turbo boost, disabled hyper-threading
RAM 188 GB
Kernel 6.1.147-172.266.amzn2023.x86_64
OS Amazon Linux 2023.8.20250818
GCC 14.2.1
Time 2025-08-29 17:20:09 UTC

Laravel 12.2.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.46565 0.46818 0.00045 0.10% 0.46637 0.00% 0.46629 0.00% 1.515 0.999 176423932 44.01 MB
PHP - 8.5-warn-nan-coercion 0.45876 0.46679 0.00075 0.16% 0.46494 -0.31% 0.46499 -0.28% -5.442 0.000 176485965 44.07 MB

Symfony 2.7.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.72046 0.73259 0.00155 0.21% 0.72261 0.00% 0.72217 0.00% 3.109 0.999 287234974 40.16 MB
PHP - 8.5-warn-nan-coercion 0.72253 0.72854 0.00100 0.14% 0.72405 0.20% 0.72384 0.23% 1.831 0.000 287280133 40.53 MB

Wordpress 6.2 main page - 100 consecutive runs, 20 warmups, 20 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.57464 0.58357 0.00228 0.39% 0.58060 0.00% 0.58151 0.00% -1.225 0.999 1119139470 43.91 MB
PHP - 8.5-warn-nan-coercion 0.57682 0.58512 0.00218 0.37% 0.58209 0.26% 0.58298 0.25% -1.361 0.000 1119813967 43.91 MB

bench.php - 100 consecutive runs, 10 warmups, 2 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.42476 0.55444 0.02724 6.28% 0.43407 0.00% 0.42786 0.00% 4.179 0.999 2020744423 26.98 MB
PHP - 8.5-warn-nan-coercion 0.42534 0.58863 0.03210 7.34% 0.43703 0.68% 0.42765 -0.05% 3.477 0.582 2020694323 27.05 MB

Comment thread Zend/Optimizer/dce.c Outdated
Comment thread Zend/zend_compile.c Outdated
Comment thread Zend/zend_compile.c Outdated
Comment thread ext/opcache/jit/zend_jit_helpers.c Outdated
Comment thread ext/opcache/jit/zend_jit_ir.c
Comment thread ext/opcache/jit/zend_jit_ir.c Outdated
Comment thread ext/opcache/jit/zend_jit_helpers.c Outdated
Comment thread Zend/Optimizer/block_pass.c Outdated
Comment on lines +485 to +486
* Those optimizations are not safe if the other operand end up being NAN
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triggered a benchmark to check the effect of this: valgrind shows no regression (changes are under 0.0x%).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder if this is not actually a problem for switch cases too now that I think of.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be worth it to check

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems I completely broke switch statements...

<?php

$nan = fdiv(0, 0);
switch ($nan) {
    case true:
        echo "true";
        break;
    case false:
        echo "false";
        break;
}
?>

Returns nothing now, even without opcache :|

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is important for canonicalization.

@Girgias
Girgias force-pushed the 8.5-warn-nan-coercion branch 2 times, most recently from 37c74ce to 7c29b7f Compare August 31, 2025 17:17
@Girgias
Girgias requested a review from arnaud-lb September 1, 2025 21:55
Comment thread ext/opcache/jit/zend_jit_ir.c Outdated
Comment thread ext/opcache/jit/zend_jit_ir.c Outdated
Comment thread Zend/Optimizer/block_pass.c Outdated
Comment on lines +485 to +486
* Those optimizations are not safe if the other operand end up being NAN
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be worth it to check

@Girgias
Girgias force-pushed the 8.5-warn-nan-coercion branch from 7c29b7f to 895b751 Compare September 3, 2025 11:21
@Girgias Girgias added this to the PHP 8.5 milestone Sep 13, 2025
@Girgias
Girgias force-pushed the 8.5-warn-nan-coercion branch 2 times, most recently from 6978b51 to 1640beb Compare September 22, 2025 01:01
@Girgias
Girgias force-pushed the 8.5-warn-nan-coercion branch from 1640beb to d82cfee Compare September 22, 2025 02:05
@Girgias
Girgias requested review from a team and arnaud-lb September 22, 2025 02:14
@Girgias
Girgias marked this pull request as ready for review September 22, 2025 08:41

@iluuu1994 iluuu1994 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't see anything obviously incorrect.

Comment thread Zend/Optimizer/block_pass.c Outdated
Comment thread Zend/Optimizer/block_pass.c Outdated
Comment thread Zend/Optimizer/block_pass.c Outdated
Comment on lines +485 to +486
* Those optimizations are not safe if the other operand end up being NAN
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is important for canonicalization.

Comment thread Zend/zend_operators.c
Comment thread Zend/zend_operators.c Outdated
Comment thread Zend/zend_operators.c Outdated
Comment thread ext/opcache/jit/zend_jit_ir.c

@edorian edorian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No RM objections 👍

@edorian
edorian requested a review from TimWolla September 22, 2025 17:27

@TimWolla TimWolla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did look in particular detail. Not happy about the optimizations we lose 😔

Comment thread Zend/zend_compile.c Outdated
Comment thread Zend/zend_operators.c
@Girgias Girgias closed this in 320fe29 Sep 23, 2025
@Girgias
Girgias deleted the 8.5-warn-nan-coercion branch September 23, 2025 10:17
@staabm

staabm commented Sep 24, 2025

Copy link
Copy Markdown
Contributor

was this change intentionally only implemented for NAN, but not for INF?

it seems INF has similar cast semantics: https://3v4l.org/lYIng

@Girgias

Girgias commented Sep 24, 2025

Copy link
Copy Markdown
Member Author

was this change intentionally only implemented for NAN, but not for INF?

it seems INF has similar cast semantics: https://3v4l.org/lYIng

Yes, that's normal. NAN is meant to be "uncomparable" and only occurs in "nonsensical" FP operations, +-INF is just a very large value, however if you try to cast them to INT you would get another warning (done in a separate PR).

nicolas-grekas added a commit to symfony/symfony that referenced this pull request Sep 25, 2025
This PR was merged into the 6.4 branch.

Discussion
----------

 do not coerce NAN to other types

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        |
| License       | MIT

see https://wiki.php.net/rfc/warnings-php-8-5#coercing_nan_to_other_types and php/php-src#19573

Commits
-------

cd93939 do not coerce NAN to other types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants