Skip to content

Check partial-application bound arguments in the creating scope#22789

Open
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/pfa-bound-arg-strict-types
Open

Check partial-application bound arguments in the creating scope#22789
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/pfa-bound-arg-strict-types

Conversation

@iliaal

@iliaal iliaal commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

The bound-argument type check in zp_bind() resolved strict_types from ZEND_ARG_USES_STRICT_TYPES(), which reads the caller of the frame creating the partial rather than the file where the partial is written. So the same f("3", ?) under strict_types=1 threw when written inside a function but silently coerced at top level, and the resulting TypeError named the enclosing function rather than the target. This passes current_frame=true into the check so strict_types resolves from the frame creating the partial, and attributes the error to the target function with zend_argument_type_error_ex.

This makes the existing eager creation-time check coherent; it does not change whether bound arguments are checked eagerly. The RFC leaves creation-time bound-argument type-check semantics unspecified, so both the eager timing (a partial throws at construction, unlike the equivalent literal closure) and these choices (creating-scope strict_types, error attributed to the target) are proposals for confirmation.

Comment thread Zend/zend_execute.c Outdated
{
return zend_check_type_slow_ex(type, arg, ref, is_return_type, is_internal,
is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES());
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I fear that hoisting the load of is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES() here may add overhead.

It seems that we could get a similar result by passing is_return_type=1 to, as in this case it will use the ZEND_CALL_USES_STRICT_TYPES() of the current frame instead of parent's?

That's unclean but we if we generalize the name of the is_return_type param to something like current_frame (frameless would work too) it would be ok.

wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, went with current_frame.

Bound-argument type checks in zp_bind() resolved strict_types from
ZEND_ARG_USES_STRICT_TYPES(), which reads the caller of the frame
creating the partial rather than the file where the partial is written,
so the same f("3", ?) threw at one call depth and silently coerced at
another, and the TypeError named the enclosing function instead of the
target. Resolve the check against the creating frame's strict_types and
attribute the error to the target function.
@iliaal
iliaal force-pushed the fix/pfa-bound-arg-strict-types branch from ba1b308 to 20b1436 Compare July 17, 2026 17:34
@iliaal
iliaal requested a review from arnaud-lb July 18, 2026 13:27
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.

2 participants