Skip to content

Zend: Inherit interfaces early#18622

Merged
Girgias merged 7 commits intophp:masterfrom
Girgias:inherit-interfaces-early
Mar 9, 2026
Merged

Zend: Inherit interfaces early#18622
Girgias merged 7 commits intophp:masterfrom
Girgias:inherit-interfaces-early

Conversation

@Girgias
Copy link
Member

@Girgias Girgias commented May 22, 2025

Needed for #18260 so that different bound types for implicit and explicitly implemented interfaces are checked correctly due to how the implementation stores the types in the HashTable.

I don't see any particular reason as to why the inheritance of interfaces was delayed, thus moving it early doesn't seem like an issue to me.

@Girgias Girgias force-pushed the inherit-interfaces-early branch from cb173f5 to 91c5a7c Compare January 3, 2026 18:29
@Girgias Girgias requested review from arnaud-lb and iluuu1994 January 4, 2026 00:06
@Girgias Girgias marked this pull request as ready for review January 4, 2026 00:06
@Girgias Girgias requested a review from dstogov as a code owner January 4, 2026 00:06
Copy link
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

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

I don't see anything blocking from moving zend_do_inherit_interfaces() at the beginning of do_interface_implementation(), but maybe wait for other reviews.

One potential BC would be that interface_gets_implemented is now called early, but this doesn't appear to be an issue in practice.

@Girgias
Copy link
Member Author

Girgias commented Jan 6, 2026

One potential BC would be that interface_gets_implemented is now called early, but this doesn't appear to be an issue in practice.

The only thing I could see happening is a different compile time error being emitted, but I didn't manage to find such a test case.

@Girgias Girgias requested a review from TimWolla January 11, 2026 21:03
Copy link
Member

@TimWolla TimWolla left a comment

Choose a reason for hiding this comment

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

Can't meaningfully comment on the change itself, as I am not familiar with the code.

Comment on lines 1592 to 1595
static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface)
{
do_implement_interface_ex(ce, iface, iface);
}
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need the _ex? distinction? The function is static and only used 2 times from what I see.

{
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) {
zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && inherited_face->interface_gets_implemented && inherited_face->interface_gets_implemented(base_iface, ce) == FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this correct? interface_gets_implemented() should be able to validate if an inteface can be implemented, but if we only pass the base_iface, we'll miss validation for the actual inherited interface. E.g. will this break if UnitEnum is added to a class implicitly through an inherited interface?

Is this change needed at all?

Copy link
Member Author

Choose a reason for hiding this comment

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

The first parameter of the interface_gets_implemented() object hook is basically never used. And if it is (as in the case for the Enum and Throwable ones) it's just for the name of it, which frankly we already know. So we probably could just get rid of it.

However passing the base_iface can clarify what explicitly implemented interface is causing the issue (as the new test I'm pushing showcases), but overall no it seems like it is not needed.

@Girgias Girgias force-pushed the inherit-interfaces-early branch from 91c5a7c to 7864a62 Compare March 9, 2026 15:46
@Girgias Girgias requested a review from iluuu1994 March 9, 2026 15:47
Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

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

Output of Zend/tests/enum/no-class-implements-backed-enum.phpt changed and looks a bit weird now, but probably not worth fixing (and is technically correct still).

@Girgias Girgias merged commit f93b170 into php:master Mar 9, 2026
19 checks passed
@Girgias Girgias deleted the inherit-interfaces-early branch March 9, 2026 22:39
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.

4 participants