Skip to content

Implement explicit send-by-ref - #2958

Closed
nikic wants to merge 5 commits into
php:masterfrom
nikic:explicitPassByRef
Closed

nikic wants to merge 5 commits into
php:masterfrom
nikic:explicitPassByRef

Conversation

@nikic

@nikic nikic commented Dec 2, 2017 •

Copy link
Copy Markdown
Member

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

Currently, in order to pass an argument by reference, the reference
has to be declared at the definition-site, but not at the call-site:

function byRef(&$ref) {}
byRef($var);

This change adds the ability to specify the by reference pass at
both the definition-site and the call-site:

function byRef(&$ref) {}
byRef(&$var);

Importantly, specifying a reference during the call will generate
an error if the argument is not also declared by-reference at the
declaration site:

function byVal($val) {}
byVal(&$val); // ERROR

This makes it different from the call-time-pass-by-reference
feature in PHP 4. If this feature is used, the reference has to
be declared at both the call- and declaration-site.

Note that it is still possible to not explicitly specify the use
of by-reference passing at the call-site. As such, the following
code remain legal:

function byRef(&$ref) {}
byRef($var);

@nikic nikic added the RFC label Dec 2, 2017
@ghost

ghost commented Dec 6, 2017

Copy link
Copy Markdown

Sounds like a great idea, however, it seems to me that it would be much more useful if there were an optional way to require this mode, and also an optional way to issue warnings when this flag is not passed.

To avoid creating more "strict modes" for users to think about, what if implicit pass-by-reference was deprecated in strict mode, issuing a warning to users who have enabled warnings?

@Fleshgrinder

Copy link
Copy Markdown
Contributor

I really like this proposal. @elijah-120 such a change to the strict mode would be possible in PHP 8. I think it's a good idea to think about that. However, that can easily be another RFC.

@nikic

nikic commented Dec 6, 2017

Copy link
Copy Markdown
Member Author

@elijah-120 I don't like the idea of rolling other, unrelated "strictness" features into the existing strict_types flag. I think the best way to do handle this would be through a separate option in combination with https://wiki.php.net/rfc/namespace_scoped_declares, but that proposal did not seem to be well-received.

@ghost

ghost commented Dec 6, 2017

Copy link
Copy Markdown

Another possible solution would be to simply deprecate the implicit feature language wide and issuing a warning with PHP 8, remove it in 10-15 years. Warnings are pretty harmless and this one is easy to correct, as opposed to deprecating something like preg_replace /e for which there is no easy fix.

The idea is that users who read the code will not have any idea that their variable is being modified. No doubt this was taken from C++, but in that case, they have both pointers and const in case they wish to do something more declarative.

It is debatable, but some style dialects (ie. google https://google.github.io/styleguide/cppguide.html#Reference_Arguments) forbid the non-const pass by reference.

Lets say you wanted to write a function that returns an additional value to a parameter - you would use a pointer, rather than trick the user with a hidden &, if not careless. PHP is pass reference for objects and copy-on-write for arrays and strings, so valid uses of pass-by-reference are limited to returning extra values and sorting an array.

@ghost

ghost commented Dec 6, 2017

Copy link
Copy Markdown

I was about to say that a fuction like "sort()" is an exception (as it is void return), but actually php array functions are not consistent about whether they modify in place or have return. For example, a user might write array_change_key_case($array) and think that it changed the case of $array, when really it does nothing. So just because you didn't assign sort($array) doesn't mean it is pass-by-reference. You have to know that.

@prgTW

prgTW commented Dec 9, 2017 •

Copy link
Copy Markdown

I like this idea although I was wondering how will this compare against typehints, both in function parameters and return typehints. Am I mistaking or this will look like this:

function &func(int &$var): int

IMHO more reasonable place for & for return typehint would be near the typehint itself:

function func(int &$var): &int

Although when not using typehints the & sign would have to back to it's original place, so I understand the reasons behind the current implementation, but when using typehints it starts to look a bit weird.

@ghost

ghost commented Dec 9, 2017

Copy link
Copy Markdown

@prgTW Yes, you are mistaken about the examples and the typehints. Check the examples in the p/r desc. My idea was just to add a warning when a variable is passed by reference but not using & at call time, but no new syntax from the proposal above.

@nikic
nikic force-pushed the explicitPassByRef branch 2 times, most recently from 858c374 to 9128867 Compare July 25, 2019 12:40
@nikic
nikic force-pushed the explicitPassByRef branch from 9128867 to 223dd72 Compare February 19, 2020 16:01
Currently, in order to pass an argument by reference, the reference
has to be declared at the definition-site, but not at the call-site:

    function byRef(&$ref) {}
    byRef($var);

This change adds the ability to specify the by reference pass at
*both* the definition-site and the call-site:

    function byRef(&$ref) {}
    byRef(&$var);

Importantly, specifying a reference during the call will generate
an error if the argument is not also declared by-reference at the
declaration site:

    function byVal($val) {}
    byVal(&$val); // ERROR

This makes it different from the call-time-pass-by-reference
feature in PHP 4. If this feature is used, the reference has to
be declared at both the call- *and* declaration-site.

Note that it is still possible to not explicitly specify the use
of by-reference passing at the call-site. As such, the following
code remain legal:

    function byRef(&$ref) {}
    byRef($var);
This is a placeholder for a mode in which & annotations are required.
Swap the numbers for the PREFER_REF and PREFER_VAL passing modes
to make the SHOULD_BE_SENT_BY_REF check more efficient.
@nikic
nikic force-pushed the explicitPassByRef branch from f0696e4 to 6814a7a Compare June 11, 2020 16:46
@SailorMax

Copy link
Copy Markdown

Today we already have PHP 8 beta1!
Any chance to got this change in release?

@Girgias

Girgias commented Aug 7, 2020

Copy link
Copy Markdown
Member

Today we already have PHP 8 beta1!
Any chance to got this change in release?

No.

@iluuu1994

Copy link
Copy Markdown
Member

@nikic Is it ok to close this PR and the associated RFC?

@nikic

nikic commented Jan 25, 2022

Copy link
Copy Markdown
Member Author

Yeah, don't plan any immediate work here.

@nikic nikic closed this Jan 25, 2022
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