Skip to content

Extend deprecation notices to is_callable($foo) and callable $foo #8823

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
wants to merge 1 commit into from

Conversation

IMSoP
Copy link
Contributor

@IMSoP IMSoP commented Jun 18, 2022

Implements https://wiki.php.net/rfc/partially-supported-callables-expand-deprecation-notices
so that uses of "self" and "parent" in is_callable() and callable
type constraints now raise a deprecation notice, independent of the
one raised when and if the callable is actually invoked.

A new flag is added to the existing check_flags parameter of
zend_is_callable / zend_is_callable_ex, for use in internal calls
that would otherwise repeat the notice multiple times. In particular,
arguments to internal function calls are checked first based on
arginfo, and then again during ZPP, so the former suppresses the
deprecation notice.

Some existing tests which raised this deprecation have been updated
to avoid the syntax, but the existing version retained for maximum
regression coverage until it is made an error.

With thanks to Juliette Reinders Folmer for the RFC and initial
investigation.

Copy link
Contributor

@jrfnl jrfnl left a comment

Choose a reason for hiding this comment

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

Based on my very limited C knowledge, this looks great!

I have verified that all tests which I'd previously identified as needing updating are included in the PR.

Amazing work @IMSoP ! Thank you so much!

Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!

@@ -3500,7 +3500,7 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
}
}

static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error) /* {{{ */
static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */
Copy link
Member

Choose a reason for hiding this comment

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

Maybe put the suppress_deprecation parameter before error, since the latter is an out-parameter.

Copy link
Contributor

Choose a reason for hiding this comment

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

But that would be inconsistent with existing zend_is_callable_check_class (ref: ee510ee#diff-210c47b94a106559d6926f51c60d8c0d39f996738af3fe79e983a409d87a6b45L3294-R3294)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, that's why I initially put it where I did; however, I think both functions are entirely internal, so I'm tempted to rearrange both, as out params on the end does feel sensible.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then note: the parameter currently before error, strict_class, is "in" here but "out" there

Copy link
Member

Choose a reason for hiding this comment

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

Well, maybe then leave this as is now.

Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

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

Thank you for the PR! This looks generally good to me, although I'm somewhat concerned regarding the "necessity" to pass IS_CALLABLE_SUPPRESS_DEPRECTATIONS to zend_is_callable_ex() what might require changes to many extensions. At the very least that would need a note in UPGRADING.INTERNALS, but I wonder whether we shouldn't invert the flag, i.e. have something like IS_CALLABLE_RAISE_DEPRECATIONS. Would that make sense?

@IMSoP
Copy link
Contributor Author

IMSoP commented Jul 12, 2022

@cmb69 My hunch - without a lot of deep thought - is that most extensions would want to trigger the deprecation, for the same reason that is_callable in userland does: because code will otherwise silently change behaviour in a future version.

The only case where you don't want it is if you're calling zend_is_callable_ex (or one of its callers, like zend_fcall_info_init) on the same variable more than once, and want to avoid duplicating the message; but that feels like it ought to be rare.

If you're just accepting a single callable, you'll probably use arginfo (which doesn't raise the deprecation) then ZPP macros (which do) at which point you've got a variable you know is callable and don't need to call it again.

@cmb69
Copy link
Member

cmb69 commented Jul 12, 2022

@IMSoP, ah, thanks for the explanation. Makes perfect sense. So we should just have a short note in UPGRADING.INTERNALS about that.

@IMSoP IMSoP force-pushed the additional-callable-deprecations branch 2 times, most recently from 95a5044 to 8ce7450 Compare July 12, 2022 18:10
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

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

Thank you!

zend_fcall_info_init, will issue deprecation notices if passed values which
are deprecated (see main UPGRADING notes). To suppress the notice, e.g. to
avoid duplicates when processing the same value multiple times, pass or add
IS_CALLABLE_SUPPRESS_DEPRECTATIONS to the check_flags parameter.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo "DEPRECTATIONS"

Suggested change
IS_CALLABLE_SUPPRESS_DEPRECTATIONS to the check_flags parameter.
IS_CALLABLE_SUPPRESS_DEPRECATIONS to the check_flags parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, well spotted! Fixed.

Implements https://wiki.php.net/rfc/partially-supported-callables-expand-deprecation-notices
so that uses of "self" and "parent" in is_callable() and callable
type constraints now raise a deprecation notice, independent of the
one raised when and if the callable is actually invoked.

A new flag is added to the existing check_flags parameter of
zend_is_callable / zend_is_callable_ex, for use in internal calls
that would otherwise repeat the notice multiple times. In particular,
arguments to internal function calls are checked first based on
arginfo, and then again during ZPP, so the former suppresses the
deprecation notice.

Some existing tests which raised this deprecation have been updated
to avoid the syntax, but the existing version retained for maximum
regression coverage until it is made an error.

With thanks to Juliette Reinders Folmer for the RFC and initial
investigation.
@IMSoP IMSoP force-pushed the additional-callable-deprecations branch from 8ce7450 to 1ef6e28 Compare July 13, 2022 17:11
@cmb69 cmb69 closed this in af15923 Jul 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants