rfc:explicit_send_by_ref

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:explicit_send_by_ref [2020/02/20 10:57] nikicrfc:explicit_send_by_ref [2022/01/25 18:21] (current) – Move to inactive ilutov
Line 1: Line 1:
-====== PHP RFC: Explicit call-site pass-by-reference ======+====== PHP RFC: Allow explicit call-site pass-by-reference annotation ======
   * Date: 2017-12-02   * Date: 2017-12-02
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
   * Proposed for: PHP 8.0   * Proposed for: PHP 8.0
   * Implementation: https://github.com/php/php-src/pull/2958   * Implementation: https://github.com/php/php-src/pull/2958
-  * Status: Under Discussion+  * Status: Inactive
  
 ===== Introduction ===== ===== Introduction =====
Line 167: Line 167:
 If the argument is a prefer-ref argument of an internal function, then adding the ''&'' annotation will pass it by reference, while not adding it will pass it by value. Outside this mode, the passing behavior would instead be determined by the VM kind of the argument operand. If the argument is a prefer-ref argument of an internal function, then adding the ''&'' annotation will pass it by reference, while not adding it will pass it by value. Outside this mode, the passing behavior would instead be determined by the VM kind of the argument operand.
  
-==== Differences to the removed "call-time pass-by-reference" feature ====+Just like ''strict_types'', the ''require_explicit_send_by_ref'' option only affects call-sites inside the file. Whether the function was declared in a file with ''require_explicit_send_by_ref'' enabled or not does not matter, only the used mode at the call-site matters.
  
-In PHP 4 (and available via deprecated ''allow_call_time_pass_reference'' option until PHP 5.4), by-reference passing was performed by adding an annotation **only** at the call-site, but not the declaration-site:+==== Forwarding references in __call, call_user_func and similar ====
  
-<code php> +The ''%%__call()%%'' and ''%%__callStatic()%%'' magic methods can be used to forward calls, but this does not work properly with by-reference arguments:
-function inc($num) { $num++; } +
- +
-$i = 0; +
-inc(&$i); +
-</code> +
- +
-This was very problematic, because the argument of any function could be forced into being a reference by adding a call-site annotation. +
- +
-PHP 5 moved towards specifying by-reference passing at the declaration-site, making by-value/by-reference passing part of the API contract of the function, as it should be. +
- +
-This proposal differs from both in that it requires the by-reference annotation at **both** the declaration-site and the call-site. It is extremely unfortunate that this hasn't been done when the original migration of the by-reference passing system happened, as it could have avoided a lot of unnecessary code churn while arriving at a better system. Given this past mistake, the next best thing we can do is address it now. +
- +
-==== Open Question: Forwarding references in __call, call_user_func and similar ==== +
- +
-The ''__call()'' and ''__callStatic()'' magic methods can be used to forward calls, but this does not work properly with by-reference arguments:+
  
 <code php> <code php>
Line 211: Line 196:
 </code> </code>
  
-The above code silently "works", but the variable ''$i'' will not actually get passed by reference. A by-reference pass does occur at the ''$this->object->$method(...$args)'' call, but at this point the value stored in ''$args'' and the variable ''$i'' have no relation to each other.+The above code silently "works", but the variable ''$i'' will not actually get passed by reference. A by-reference pass does occur at the ''%%$this->object->$method(...$args)%%'' call, but at this point the value stored in ''$args'' and the variable ''$i'' have no relation to each other.
  
-The explicit call-site annotation could be used to allow passing the variable by reference:+The explicit call-site annotation can be used to allow passing the variable by reference:
  
 <code php> <code php>
Line 222: Line 207:
 </code> </code>
  
-This would make the corresponding element in ''$args'' be a reference, which the argument unpack would pass on to the called function. Making this work would require introducing a new internal argument passing mode like ''prefer-val'', which permits both by-value and by-reference passing, but prefers by-value passing by default (unlike the existing ''prefer-ref'').+This will make the corresponding element in ''$args'' be a reference, which the argument unpack then passes on to the called function.
  
-A similar problem also exists with ''call_user_func()'', which is not capable of calling functions that have by-reference parameters properlyThe same mechanism could be used to support this.+Similarly, ''call_user_func()'' can now be used to call functions that accept by-reference parameters: 
 + 
 +<code php> 
 +function inc(&$i) { $i++; } 
 + 
 +$i = 0; 
 +call_user_func('inc', $i); 
 +// Warning: inc() expects argument #1 ($i) to be passed by reference, value given 
 +var_dump($i); // int(0) 
 + 
 +$i = 0; 
 +call_user_func('inc', &$i); 
 +var_dump($i); // int(1) 
 +</code> 
 + 
 +Both of these features are achieved by introducing a new internal argument passing mode ''prefer-val''. Just like ''prefer-ref'' it accepts both by-value and by-reference, but prefers by-value passing unless by-reference passing is forced by a call-site annotation. 
 + 
 +==== Differences to the removed "call-time pass-by-reference" feature ==== 
 + 
 +In PHP 4 (and available via deprecated ''allow_call_time_pass_reference'' option until PHP 5.4), by-reference passing was performed by adding an annotation **only** at the call-site, but not the declaration-site: 
 + 
 +<code php> 
 +function inc($num) { $num++; } 
 + 
 +$i = 0; 
 +inc(&$i); 
 +</code> 
 + 
 +This was very problematic, because the argument of any function could be forced into being a reference by adding a call-site annotation. 
 + 
 +PHP 5 moved towards specifying by-reference passing at the declaration-site, making by-value/by-reference passing part of the API contract of the function, as it should be. 
 + 
 +This proposal differs from both in that it requires the by-reference annotation at **both** the declaration-site and the call-siteIt is extremely unfortunate that this hasn't been done when the original migration of the by-reference passing system happened, as it could have avoided a lot of unnecessary code churn while arriving at a better system. Given this past mistake, the next best thing we can do is address it now.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
rfc/explicit_send_by_ref.1582196220.txt.gz · Last modified: 2020/02/20 10:57 by nikic