rfc:nullsafe_operator
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:nullsafe_operator [2020/07/12 13:36] – Disallow usage of ?-> by reference ilutov | rfc:nullsafe_operator [2020/07/31 08:55] (current) – Close vote ilutov | ||
---|---|---|---|
Line 3: | Line 3: | ||
* Date: 2020-06-02 | * Date: 2020-06-02 | ||
* Author: Ilija Tovilo, tovilo.ilija@gmail.com | * Author: Ilija Tovilo, tovilo.ilija@gmail.com | ||
- | * Status: | + | * Status: |
* Target Version: PHP 8.0 | * Target Version: PHP 8.0 | ||
* Implementation: | * Implementation: | ||
Line 10: | Line 10: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | This RFC proposes | + | This RFC proposes |
===== Proposal ===== | ===== Proposal ===== | ||
Line 76: | Line 76: | ||
* Nullsafe method call ('' | * Nullsafe method call ('' | ||
* Static method call ('' | * Static method call ('' | ||
- | * Assignment ('' | ||
- | * Post/pre increment ('' | ||
The following elements will cause new sub-chains. | The following elements will cause new sub-chains. | ||
- | * Right hand side of an assignment | ||
* Arguments in a function call | * Arguments in a function call | ||
* The expression in '' | * The expression in '' | ||
Line 103: | Line 100: | ||
// | // | ||
// If $c is null chain 2 is aborted, method d() isn't called, null is passed to `$a-> | // If $c is null chain 2 is aborted, method d() isn't called, null is passed to `$a-> | ||
- | |||
- | | ||
- | // -------------------- chain 1 | ||
- | // ------- chain 2 | ||
- | // If $foo is null chain 1 is aborted, `$a-> | ||
- | |||
- | | ||
- | // ------------ chain 1 | ||
- | // If $foo is null, chain 1 is aborted, ++ is skipped | ||
</ | </ | ||
==== Rationale ==== | ==== Rationale ==== | ||
Line 121: | Line 109: | ||
$foo? | $foo? | ||
</ | </ | ||
- | The evaluation of '' | + | The evaluation of '' |
**2. You can see which methods/ | **2. You can see which methods/ | ||
Line 131: | Line 119: | ||
Without short circuiting every subsequent method call and property access in the chain will require using the nullsafe operator or you will get a “Call to a member function on null” error. With short circuiting this isn’t necessary which makes it more obvious which methods/ | Without short circuiting every subsequent method call and property access in the chain will require using the nullsafe operator or you will get a “Call to a member function on null” error. With short circuiting this isn’t necessary which makes it more obvious which methods/ | ||
- | **3. Allows for nullsafe operator in write context** | + | **3. Mixing with other operators** |
- | + | ||
- | <code php> | + | |
- | $foo = null; | + | |
- | $foo? | + | |
- | var_dump($foo); | + | |
- | + | ||
- | // Without short circuiting: | + | |
- | // Fatal error: Can't use nullsafe result value in write context | + | |
- | + | ||
- | // With short circuiting: | + | |
- | // NULL | + | |
- | </ | + | |
- | Without short circuiting the assignment to a nullsafe property would be illegal because it produces an r-value (a value that cannot be assigned to). With short circuiting if a nullsafe operation on the left hand side of the assignment fails the assignment is simply skipped. | + | |
- | + | ||
- | **4. Mixing with other operators** | + | |
<code php> | <code php> | ||
Line 189: | Line 162: | ||
===== Syntax choice ===== | ===== Syntax choice ===== | ||
- | The '' | + | The '' |
- | ===== Edge cases ===== | + | ===== Forbidden usages |
- | ==== Nullsafe operator in parameters passed by reference | + | ==== Nullsafe operator in write context |
- | The nullsafe operator | + | Using the nullsafe operator |
<code php> | <code php> | ||
- | takes_ref($foo? | + | $foo? |
- | // Error: Cannot pass parameter 1 by reference | + | // Can't use nullsafe operator in write context |
+ | |||
+ | foreach | ||
+ | // Can't use nullsafe operator in write context | ||
+ | |||
+ | unset($foo? | ||
+ | // Can't use nullsafe operator in write context | ||
+ | |||
+ | [$foo? | ||
+ | // Assignments can only happen to writable values | ||
</ | </ | ||
- | The code above could loosely be translated | + | It was previously suggested |
+ | |||
+ | ==== References ==== | ||
+ | |||
+ | Taking the reference of a nullsafe chain is not allowed. This is because references require l-values (memory locations, like variables or properties) but the nullsafe operator can sometimes return | ||
<code php> | <code php> | ||
+ | $x = & | ||
+ | |||
+ | // Could loosely be translated to | ||
+ | |||
if ($foo !== null) { | if ($foo !== null) { | ||
- | | + | |
} else { | } else { | ||
- | | + | |
+ | // Only variables should be assigned by reference | ||
} | } | ||
</ | </ | ||
- | This code is not valid, as it would throw a “Fatal error: Only variables can be passed by reference” error whenever '' | + | For this reason, the following examples are disallowed. |
- | ==== Nullsafe operator in values returned by reference | + | <code php> |
+ | // 1 | ||
+ | $x = & | ||
+ | // Compiler error: Cannot take reference | ||
- | Trying to use the nullsafe operator in values returned | + | // 2 |
+ | takes_ref($foo? | ||
+ | // Error: Cannot pass parameter 1 by reference | ||
- | <code php> | + | // 3 |
function & | function & | ||
return $foo? | return $foo? | ||
+ | // Compiler error: Cannot take reference of a nullsafe chain | ||
} | } | ||
- | |||
- | $barRef = & | ||
- | // Notice: Only variable references should be returned by reference | ||
- | $barRef = ' | ||
- | var_dump($foo-> | ||
</ | </ | ||
- | This is consistent with trying to pass other r-values by reference. | + | Example 2 is a runtime error because we cannot know at compile time if the given parameter allows passing |
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 240: | Line 232: | ||
===== Vote ===== | ===== Vote ===== | ||
- | … | + | Voting starts 2020-07-17 and ends 2020-07-31. |
+ | |||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ |
rfc/nullsafe_operator.1594560963.txt.gz · Last modified: 2020/07/12 13:36 by ilutov