Skip to content

Break reference after foreach by reference #7364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed

Conversation

nikic
Copy link
Member

@nikic nikic commented Aug 12, 2021

After foreach ($array as &$val) {} perform a reference-unwrap
on $val. This means that it will become a normal value rather
than a reference to the last element of $array.

This fixes the common WTF where

foreach ($array as &$val) {}
foreach ($array as $val) {}

will change the second-to-last element of the array to be the
same as the last element.

RFC: https://wiki.php.net/rfc/foreach_unwrap_ref

Copy link
Contributor

@TysonAndre TysonAndre left a comment

Choose a reason for hiding this comment

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

Seems useful to me to have as the RFC currently is to avoid a common source of bugs.

The intended behavior of break 2; and continue 2; or goto should probably be noted (i.e. references are only converted to variables if the end of the loop is reached normally

@jpresutti
Copy link

And what if someone is intentionally using this behavior? I'm not, but to act like no one could is ridiculous. Is it a potential footgun? Yes. Should all footguns be prevented? No.

@drealecs
Copy link

And what if someone is intentionally using this behavior? I'm not, but to act like no one could is ridiculous. Is it a potential footgun? Yes. Should all footguns be prevented? No.

I think you can put a safety lock to it by making the user do something like

foreach ($a as &$x) {
    $xRef = &$x;
}
$xRef = ...

if they really want to use it

@nikic
Copy link
Member Author

nikic commented Aug 23, 2021

And what if someone is intentionally using this behavior? I'm not, but to act like no one could is ridiculous.

This is acknowledged in https://wiki.php.net/rfc/foreach_unwrap_ref#backward_incompatible_changes.

Also, please leave RFC feedback on the PHP internals mailing list rather than GitHub.

@jpresutti
Copy link

And what if someone is intentionally using this behavior? I'm not, but to act like no one could is ridiculous.

This is acknowledged in https://wiki.php.net/rfc/foreach_unwrap_ref#backward_incompatible_changes.

Also, please leave RFC feedback on the PHP internals mailing list rather than GitHub.

It's 2021, a mailing list is kinda archaic.

@nikic
Copy link
Member Author

nikic commented Aug 25, 2021

The intended behavior of break 2; and continue 2; or goto should probably be noted (i.e. references are only converted to variables if the end of the loop is reached normally

I hadn't originally considered this, but to me it would make the most sense to have the same behavior even if multi-level break / goto is used. Will have to push the reference unwrapping to the unwind stack.

@nikic nikic force-pushed the foreach-ref branch 2 times, most recently from 0ffe0bc to 8bd6889 Compare August 27, 2021 08:33
After `foreach ($array as &$val) {}` perform a reference-unwrap
on `$val`. This means that it will become a normal value rather
than a reference to the last element of `$array`.

This fixes the common WTF where

    foreach ($array as &$val) {}
    foreach ($array as $val) {}

will change the second-to-last element of the array to be the
same as the last element.
@nikic
Copy link
Member Author

nikic commented Nov 25, 2021

This RFC has been withdrawn.

@nikic nikic closed this Nov 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants