> - RFC: https://wiki.php.net/rfc/bound_erased_generic_types > - Implementation: https://github.com/php/php-src/pull/21969
Hello Internals, Status update: RFC is now at v0.22. Two changes are worth flagging. 1. Substituted runtime contracts are now enforced end-to-end on inherited members. A child class binding a generic parent now enforces the substituted parameter and return types at runtime at every site the substitution touches: method and constructor entry (including defaults and per-element variadics), return values, backed property storage, property hook get/set signatures, and trait-imported method and property types. Enforcement is uniform regardless of the parent's bound, a child binding T to int on Box<T : mixed> rejects non-int values everywhere, not just where the parent's bound happened to be stricter. This collapses the "body bytecode is not recompiled per substitution" caveat from earlier drafts. The specific case the previous Limitations text called out as observable (a virtual hook returning a hardcoded value of the wrong substituted type) now throws an error. The Limitations section is down to three bullets: type-argument erasure (Box<int> accepts a Box<string> because the runtime check is instanceof Box), turbofish doesn't tighten parameters, and method-level T-bound resolves to the bound rather than the per-instance instantiation. 2. Reflection: plural ancestor-binding getter. `ReflectionClass::getGenericArgumentsForParentInterface()` now returns `list<list<ReflectionType>>`. A class binding the same generic interface multiple times, gets every binding as a separate outer-list entry. The previous singular shape silently dropped all but one. ( e.g. `class Bar implements Foo<int>, Foo<string>`) Cheers, Seifeddine.
