Skip to content

Deprecate curly brace syntax for array/string offset access #4416

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

Conversation

theodorejb
Copy link
Contributor

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

Migration script: https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863

@rjhdby wrote the initial deprecation patch and migration script. I added commits to improve the script, convert uses in run-tests.php, and move the migration script to a GitHub gist (since I don't think it makes sense to maintain it long-term in php-src).

@petk petk added the RFC label Jul 15, 2019
Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

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

Please check whether const FOO = "BAR"{0} throws a deprecation warning. You might need additional handling in zend_compile_const_expr or maybe zend_eval_const_expr.

@nikic nikic added this to the PHP 7.4 milestone Jul 16, 2019
@theodorejb
Copy link
Contributor Author

theodorejb commented Jul 16, 2019

@nikic I hope I'm doing things the right way. It seems kind of hacky how ast->child[0]->attr is overwritten here: https://github.com/theodorejb/php-src/blob/41878385bd976fb566f73496dc759a6093f6704f/Zend/zend_compile.c#L8811. I changed the value of ZEND_ALTERNATIVE_ARRAY_SYNTAX to avoid conflicting with ZEND_DIM_IS, but there's still the following bug:

const A = [1 => [[]]];

const T_0 = A[1]{0}; // produces deprecation notice as expected
const T_1 = A[1]{0} ?? 1; // fails to produce deprecation notice

@theodorejb
Copy link
Contributor Author

@nikic I worked around the issue of ast->child[0]->attr being overwritten by treating it as a bitmask instead of a single value. Still seems hacky but it works!

@theodorejb theodorejb force-pushed the deprecate_alternate_array_access branch from d64424f to 8ddac63 Compare July 17, 2019 12:31
@theodorejb theodorejb force-pushed the deprecate_alternate_array_access branch from 8ddac63 to 8131dbc Compare July 17, 2019 13:08
@nikic
Copy link
Member

nikic commented Jul 17, 2019

As mentioned above, it is better to throw the deprecation warning in the compiler so that tooling that only parses (php-ast extension and token_get_all in parse mode) does not generate deprecation warnings. I think the patch you used to have was right. Instead of using a bitmask you might want to remove the flag after emitting the deprecation warning in eval_const_expr -- I think duplicate warnings might happen otherwise.

@theodorejb
Copy link
Contributor Author

@nikic Okay, I reverted the direct parser implementation to avoid warnings for tooling that needs to parse PHP files.

Without the bitmask approach, though, I'm not sure how to generate the correct deprecation warning when the null coalesce operator is used (since it otherwise overwrites the attr property on child nodes before they are evaluated).

Can you think of an example that would produce duplicate warnings?

@nikic
Copy link
Member

nikic commented Jul 18, 2019

@theodorejb Okay, seeing where the DIM_IS flag is being set, the bitmask is fine. I'd suggest renaming to ZEND_DIM_ALTERNATIVE_SYNTAX and placing the defines next to each other as (1 << 0) and (1 << 1) to make clear that this is a bitmask though.

For the duplicate warning, I'm thinking something like [$x{0}] might trigger it -- I think this will try to const-eval the $x{0}, throw a deprecation warning there and then again during compilation.

@nikic
Copy link
Member

nikic commented Jul 19, 2019

Merged as d574df6, thanks!

@nikic nikic closed this Jul 19, 2019
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Jul 22, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

## Implementation notes

Based on a lot of testing, I have come to the conclusion that the curly braces for array access *only* worked when used on a variable/property.

It never worked on constant arrays, function calls etc etc

Note:
* Verified that curly brace syntax never worked for function array string dereferencing. See https://3v4l.org/oWnqF
* Verified that curly brace syntax never worked for function array dereferencing. See https://3v4l.org/g9jGG
* Verified that curly brace syntax never worked for new class member access. See https://3v4l.org/9PkVW

## Fixes

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

*Important*: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.

## Tests run

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and the results are 100% the same.
@theodorejb theodorejb deleted the deprecate_alternate_array_access branch July 22, 2019 16:10
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Jul 22, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

Based on a lot of testing, I have come to the conclusion that the curly braces for array access *only* worked when used on a variable/property.

It never worked on constant arrays, function calls etc etc

Note:
* Verified that curly brace syntax never worked for function array string dereferencing. See https://3v4l.org/oWnqF
* Verified that curly brace syntax never worked for function array dereferencing. See https://3v4l.org/g9jGG
* Verified that curly brace syntax never worked for new class member access. See https://3v4l.org/9PkVW

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

*Important*: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and the results are 100% the same.
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Jul 29, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

Based on a lot of testing, I have come to the conclusion that the curly braces for array access worked in quite a lot of cases, though mostly since PHP 7.0.

The other sniffs which should take curly brace access into account - `NewArrayStringDereferencing`, `NewClassMemberAccess` and `NewFunctionArrayDereferencing` - have been adjusted in separate PRs.

This PR can only be merged after those PRs have been merged.

### Other tests

Based on the above mentioned tests, I also found that - yes, curly brace array access is supported on constants, but only when the first set of braces is square brackets.
See:
* https://3v4l.org/WIUHk
* https://3v4l.org/OWSq6
* https://3v4l.org/e6YWk

### Fixer

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

*Important*: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.
A typical `.fixed` file which would be expected by the PHPCS native test suite to verify the fixer results _is_ included with this PR though.

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and for the compared results, the outcome is 100% the same.
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Jul 29, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

## Implementation notes

Based on a lot of testing, I have come to the conclusion that the curly braces for array access worked in quite a lot of cases, though mostly since PHP 7.0.

The other sniffs which should take curly brace access into account - `NewArrayStringDereferencing`, `NewClassMemberAccess` and `NewFunctionArrayDereferencing` - have been adjusted in separate PRs.

This PR can only be merged after those PRs have been merged as it re-uses logic from those sniffs.

### Other tests

Based on the above mentioned tests, I also found that - yes, curly brace array access is supported on constants, but only when the first set of braces is square brackets.
See:
* https://3v4l.org/WIUHk
* https://3v4l.org/OWSq6
* https://3v4l.org/e6YWk

## Auto-fixing

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

**Important**: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.
A typical `.fixed` file which would be expected by the PHPCS native test suite to verify the fixer results _is_ included with this PR though.

## Tests run

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and for the compared results, the outcome is 100% the same.
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Aug 21, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

## Implementation notes

Based on a lot of testing, I have come to the conclusion that the curly braces for array access worked in quite a lot of cases, though mostly since PHP 7.0.

The other sniffs which should take curly brace access into account - `NewArrayStringDereferencing`, `NewClassMemberAccess` and `NewFunctionArrayDereferencing` - have been adjusted in separate PRs.

This PR can only be merged after those PRs have been merged as it re-uses logic from those sniffs.

### Other tests

Based on the above mentioned tests, I also found that - yes, curly brace array access is supported on constants, but only when the first set of braces is square brackets.
See:
* https://3v4l.org/WIUHk
* https://3v4l.org/OWSq6
* https://3v4l.org/e6YWk

## Auto-fixing

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

**Important**: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.
A typical `.fixed` file which would be expected by the PHPCS native test suite to verify the fixer results _is_ included with this PR though.

## Tests run

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and for the compared results, the outcome is 100% the same.
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Aug 28, 2019
> The array and string offset access syntax using curly braces is deprecated.
> Use $str[$idx] instead of $str{$idx}.

Refs:
* https://wiki.php.net/rfc/deprecate_curly_braces_array_access
* https://github.com/php/php-src/blob/ef165b4422f4cef60f963833dddffa26fe1b2759/UPGRADING#L351-L353
* php/php-src#4416
* php/php-src@d574df6

## Implementation notes

Based on a lot of testing, I have come to the conclusion that the curly braces for array access worked in quite a lot of cases, though mostly since PHP 7.0.

The other sniffs which should take curly brace access into account - `NewArrayStringDereferencing`, `NewClassMemberAccess` and `NewFunctionArrayDereferencing` - have been adjusted in separate PRs.

This PR can only be merged after those PRs have been merged as it re-uses logic from those sniffs.

### Other tests

Based on the above mentioned tests, I also found that - yes, curly brace array access is supported on constants, but only when the first set of braces is square brackets.
See:
* https://3v4l.org/WIUHk
* https://3v4l.org/OWSq6
* https://3v4l.org/e6YWk

## Auto-fixing

In contrast to any other PHPCompatibility sniff, this sniff contains an auto-fixer.

For larger codebases, this issue can be quite time-consuming to fix, while fixing this automatically is trivial.

This also makes this sniff a fully fledged alternative to the [migration script](https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863) provided by PHP itself.

**Important**: At this moment, the PHPCompatibility unit test suite does not contain a mechanism to test the fixer.
A typical `.fixed` file which would be expected by the PHPCS native test suite to verify the fixer results _is_ included with this PR though.

## Tests run

I have run the sniff, as well as the fixer, over a number of medium to large codebases and have found _no_ false positives.

I have compared the results of a few of these projects with [the list compiled by Nikita](https://gist.github.com/nikic/b5f811e0423bf051f4492cd6e0c0273e) and for the compared results, the outcome is 100% the same.
@Jan-E
Copy link
Contributor

Jan-E commented Jul 7, 2020

Looks like you missed 2 places in the win32 build system:
https://github.com/php/php-src/blob/PHP-7.4/win32/build/mkdist.php#L189
https://github.com/php/php-src/blob/PHP-7.4/win32/build/mkdist.php#L192

Since the windows build system has moved to using PHP 7.4 the deprecation warning is also shown when building PHP 7.3. @cmb69 something for you to correct?

@cmb69
Copy link
Member

cmb69 commented Jul 7, 2020

@Jan-E, indeed, that needs to be fixed. Thanks for reporting! :)

@Jan-E
Copy link
Contributor

Jan-E commented Jul 7, 2020

PHP 7.2 has the same problem, but this is not exactly a security fix;
https://github.com/php/php-src/blob/PHP-7.2/win32/build/mkdist.php#L194

@cmb69
Copy link
Member

cmb69 commented Jul 7, 2020

I'm not concerned about PHP 7.2. This will EOL around the time PHP 8.0.0 will be released, and certainly the SDK will not be updated to PHP 8.0 soon afterwards. And if anybody will build PHP 7.2 after the SDK had been updated to PHP 8.0, they still could use a slightly older SDK version (or apply the fix themselves). And with PHP 7.4, it's just a deprecation notice.

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.

7 participants