-
-
Notifications
You must be signed in to change notification settings - Fork 205
Description
Related to #1589
Analysis
The RFC proposes multiple changes in PHP 8.3.
1. If $step is a float but is compatible with int, interpret it as an integer
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(3, 2, 1.0) |
[3.0, 2.0] |
[3, 2] |
https://3v4l.org/tvH5N
2. TypeErrors thrown when passing objects, resources, and arrays to range()
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(gmp_init(3), 2, 1) |
[3, 2] (some types, like GMP, can be converted to int) |
[3, 2] |
range([3], 2, 1) |
[1, 2] |
❌ TypeError: Argument #1 ($start) must be of type... |
range(new stdClass(), 2, 1) |
[1, 2] |
❌ TypeError: Argument #1 ($start) must be of type... |
range(STDIN, 2, 1) |
[1, 2] |
❌ TypeError: Argument #1 ($start) must be of type... |
https://3v4l.org/PDXYh
3. Deprecation warning to be emitted when passing null
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(null, 2, 1) |
[0, 1, 2] |
[0, 1, 2] |
https://3v4l.org/v8jNN
4. Emit an E_WARNING when $start or $end is the empty string, and cast the value to 0
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range('', 2, 1) |
[0, 1, 2] |
[0, 1, 2] |
https://3v4l.org/WZWUY
5. Emit an E_WARNING when $start or $end has more than one byte if it is a non-numeric string
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range('3a', '2a', 1) |
["3", "2"] |
["3", "2"] |
range('a3', 'a2', 1) |
["a"] |
["a"] |
https://3v4l.org/mCtv5
6. Emit an E_WARNING when $start or $end is cast to an integer because the other boundary input is a number
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(3, 'a', 1) |
[3, 2, 1, 0] |
[3, 2, 1, 0] |
https://3v4l.org/WoOic
Note: when the string is empty, the result is the same, but the warning differs slightly ("casted" vs "converted"). See point 4 above.
7. Emit an E_WARNING when $step is a float when trying to generate a range of characters, except if both boundary inputs are numeric strings
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range('5', '6', 0.5) |
[5.0, 5.5, 6.0] |
[5.0, 5.5, 6.0] (no change) |
range('a', 'b', 0.5) |
[0.0] |
[0.0] |
https://3v4l.org/3v9gd
8. Throw value errors if $start, $end, or $step is a non-finite float (-INF, INF, NAN)
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(3, 2, -INF) |
❌ ValueError: ... must not exceed the specified range | ❌ ValueError: ... must be a finite number, INF provided |
range(3, 2, INF) |
❌ ValueError: ... must not exceed the specified range | ❌ ValueError: ... must be a finite number, INF provided |
range(3, 2, NAN) |
❌ ValueError: ... must not exceed the specified range | ❌ ValueError: ... must be a finite number, NAN provided |
https://3v4l.org/njIN7
9. Throw a more descriptive ValueError when $step is zero
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(3, 2, 0) |
❌ ValueError: ... must not exceed the specified range | ❌ ValueError: ... must be a finite number, INF provided |
https://3v4l.org/8MTLO
10. Throw a ValueError when passing a negative $step for increasing ranges
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(3, 2, -1) |
[3, 2] | [3, 2] (no change for decreasing ranges) |
range(3, 4, -1) |
[3, 4] | ❌ ValueError: ... must be greater than 0 for increasing ranges |
https://3v4l.org/vIamn
11. Produce a list of characters if one of the boundary inputs is a string digit instead of casting the other input to int
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range('9', 'a', 1) |
[9, 8, 7, ...] (10 int values) |
["9", ":", ";", "<", ...] (41 ASCII values) |
https://3v4l.org/SZh8M
12. Other behavior tested
| Syntax | PHP 8.2 | PHP 8.3 |
|---|---|---|
range(false, 2, 1) |
[0, 1, 2] |
[0, 1, 2] (no change) |
range(true, 2, 1) |
[1, 2] |
[1, 2] (no change) |
range('3.5', 2, 1) |
[3, 2] |
[3.5, 2.5] (now a float) |
https://3v4l.org/vk4nK
Note: I couldn't find the last behavior change in the RFC, migration docs, or the range() changelog (see references below).
Top 2000 Packages
Analysis already performed and documented by the RFC's author.
Detection in PHP 8.2
Since this is a change in semantics, no detection in PHP 8.2 is required. Pre-existing errors and warnings are out of scope for PHPCompatibility (@jrfnl please confirm).
Detection in PHP 8.3
- Calls with arguments that become ValueErrors or TypeErrors: ❌ Invalid, error
- Calls with arguments that become warnings: ️
⚠️ Invalid, warning - Calls with arguments resulting in other behavior changes, like becoming floats in
range('3.5', 2, 1): ️⚠️ BC break, warning
Syntax Variations
- The 12 sections above cover all the semantic and TypeError variations.
- Function call variations
- Namespace false positives;
- Other false positives
Detectability
- Calls to the
rangenative function: ✅ Detectable with PHPCompatibility. - Argument types and values passed to
range:⚠️ Limitations in PHPCompatibility, but the prevalence of literals (per the RFC) suggests we should be able to detect a significant number of cases.