Skip to content
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

Deprecate required param after optional #5067

Closed
wants to merge 2 commits into from

Conversation

nikic
Copy link
Member

@nikic nikic commented Jan 9, 2020

This addresses https://bugs.php.net/bug.php?id=53399.

Historically, having an "optional" parameter before a required one was useful for poor man's nullable types. That is, one could write function test(FooBar $param = null, $param2) to get an effective ?FooBar typehint on PHP versions that did not natively support it.

Since we've had nullable types since PHP 7.1 now, having a required parameter after an optional one is increasingly likely a bug rather than an intentional workaround, so we should throw a warning for this case.

@nikic nikic added the Feature label Jan 9, 2020
@nikic nikic force-pushed the required-after-optional-warning branch from 9474411 to c5de589 Compare Jan 9, 2020
Copy link
Member

@carusogabriel carusogabriel left a comment

👍 For this one

} else {
opcode = ZEND_RECV;
default_node.op_type = IS_UNUSED;
op_array->required_num_args = i + 1;
if (have_optional_param) {
zend_error(E_COMPILE_WARNING, "Required parameter $%s follows optional parameter",

Choose a reason for hiding this comment

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

Maybe the message should also say this will become an error in a later PHP version. (If that is the plan)

@nikic nikic changed the title Throw warning if required param follows optional Deprecate required param after optional Jan 9, 2020
@nikic
Copy link
Member Author

@nikic nikic commented Jan 9, 2020

Per the ML discussion, I've changed this to throw a deprecation warning instead.

@ostrolucky
Copy link

@ostrolucky ostrolucky commented Jan 9, 2020

This looks controversial to me, there should be an RFC. string foo = null is common in other languages.

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 9, 2020

This looks controversial to me, there should be an RFC. string foo = null is common in other languages.

This is not to remove this altogether, it's to deprecate the fact that you have a default value on some parameters before some which don't, meaning that you have an optional param before mandatory ones.

@ostrolucky
Copy link

@ostrolucky ostrolucky commented Jan 9, 2020

I stand corrected, that shouldn't be controversial 👍

@vvval
Copy link

@vvval vvval commented Jan 13, 2020

And what if an optional param doesn't have a type?

/**
 * @param mixed|null $param
 * @param            $param2
 */
function test($param = null, $param2)

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 13, 2020

And what if an optional param doesn't have a type?

/**
 * @param mixed|null $param
 * @param            $param2
 */
function test($param = null, $param2)

This case is also covered and would be deprecated.

@ostrolucky
Copy link

@ostrolucky ostrolucky commented Jan 13, 2020

And what if an optional param doesn't have a type?

/**
 * @param mixed|null $param
 * @param            $param2
 */
function test($param = null, $param2)

This case is also covered and would be deprecated.

What's the alternative for that though? There is no mixed type so you can't replace it with function test(?mixed $param, $param)

edit: we can do function test($param, $param2) of course 🤦‍♂

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 13, 2020

And what if an optional param doesn't have a type?

/**
 * @param mixed|null $param
 * @param            $param2
 */
function test($param = null, $param2)

This case is also covered and would be deprecated.

What's the alternative for that though? There is no mixed type so you can't replace it with function test(?mixed $param, $param)

The alternative is to have your optional parameter in second place instead of first.

@ostrolucky
Copy link

@ostrolucky ostrolucky commented Jan 13, 2020

You can't swap arguments willy nilly, that would cause BC breaks.

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 13, 2020

You can't swap arguments willy nilly, that would cause BC breaks.

There will be a full PHP major cycle for libraries to fix this.
And BC should not be kept for clearly nonsensical code IMHO.

@nikic
Copy link
Member Author

@nikic nikic commented Jan 13, 2020

function test($param = null, $param2) is strictly equivalent to function test($param, $param2). You can just drop the useless and confusing = null, there are no BC implications whatsoever for that case.

@nikic nikic force-pushed the required-after-optional-warning branch from 60b7d5f to b63436a Compare Feb 5, 2020
@carusogabriel carusogabriel added this to the PHP 8.0 milestone May 29, 2020
leofeyer pushed a commit to contao/contao that referenced this issue Feb 11, 2022
…tructors (see #4065)

Description
-----------

Fixes #4055

This PR swaps the first two parameters of the `AsContentElement` and `AsFrontendModule` constructors. This was not released yet, so no BC issue.

Background info: As of PHP8.0 having optional parameters before mandatory ones is deprecated. Here is an explanation why the current code did not trigger a deprecation warning and behaved just like two mandatory parameters: php/php-src#5067 (comment)

Commits
-------

9058274 fix order of parameters
6df2476 adjust tests
5bd86a5 use miscellaneous as the default type and fix variadic argument type hint
4356ed6 prevent PHP<8.0 jobs from autoloading test cases with PHP8 syntax
8a1d2d8 add 'mixed' type hint for variadic attributes
1f396f9 improve comment
942fc37 Update core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php
e413bf3 🦊
leofeyer pushed a commit to contao/core-bundle that referenced this issue Feb 11, 2022
…tructors (see #4065)

Description
-----------

Fixes #4055

This PR swaps the first two parameters of the `AsContentElement` and `AsFrontendModule` constructors. This was not released yet, so no BC issue.

Background info: As of PHP8.0 having optional parameters before mandatory ones is deprecated. Here is an explanation why the current code did not trigger a deprecation warning and behaved just like two mandatory parameters: php/php-src#5067 (comment)

Commits
-------

90582748 fix order of parameters
6df2476e adjust tests
5bd86a50 use miscellaneous as the default type and fix variadic argument type hint
4356ed66 prevent PHP<8.0 jobs from autoloading test cases with PHP8 syntax
8a1d2d82 add 'mixed' type hint for variadic attributes
1f396f9f improve comment
942fc372 Update core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php
e413bf33 🦊
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.

None yet

7 participants