Tag:
Branch:
Tree:
7768ce177e
master
speed_build
v0.0.1
v0.0.2
v0.0.3
v0.0.4
v0.0.5
v0.0.6
v0.0.7
v0.1.0
v0.4.0
v0.4.1
v0.6.1
v0.6.2
v0.6.5
v0.6.6
v0.6.8
${ noResults }
1 Commits (7768ce177ef2f411d4fe04c6f435b387903b642f)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
fde9e3a9d8
|
fix(translator): covariant typed class constants and interface constant contracts (#58) --skip-tests
* fix(translator): make typed class-constant overrides covariant
checkConstantOverride() required exact type equality between a child
constant and the parent's declared type, rejecting valid PHP 8.3
programs: class constant types are covariant, so a child may narrow
(parent `const int|string X` overridden by `const int X`, or
`?int` by `int`) but never widen or move to an unrelated type
(Zend: "Type of B::X must be compatible with A::X of type int").
Composite declared types (unions, nullables) were also collapsed to a
single variant type at parse time, making them unrepresentable in the
check. ConstantDef now records the accepted-types DNF of its declared
type (built by the existing buildTypeCheckFromNode machinery in a
parseClassConstDef override, while the declaration's name-resolution
context is still active), and the override check reuses the DNF
clause-subtyping used for covariant returns. Untyped parent constants
remain unchecked, and a typed parent still requires a typed child.
* fix(translator): validate interface constant contracts
Interface constants were never validated: checkInterfaceImplementation()
had no constants loop and checkConstantOverride() only walks the class
extends chain. Incompatible retypings, final-constant overrides,
narrowed visibility and ambiguous multi-interface inheritance were all
accepted (all fatal in Zend 8.4).
Model Zend's constants-table merge (zend_do_inheritance +
do_inherit_constant_check): a class-like's effective table is built from
the parent class's table (private constants are not inherited), its own
declarations, then its interfaces, each entry keeping the ORIGINAL
declaring class/interface. When a same-name constant arrives from a
different declaration:
- a FINAL inherited constant cannot be overridden — "C::X cannot
override final constant I::X" — including through an ancestor class
that implemented the interface (the origin travels with the entry);
- two different declarations are ambiguous unless the type declares
the constant itself — "Class C inherits both I1::X and I2::X,
which is ambiguous" (a diamond of one declaration is fine);
- an override of an interface constant must stay public — "Access
level to C::X must be public (as in interface I)";
- a typed interface constant requires a typed, covariant override; an
untyped one may be redefined freely.
The same validation runs for interfaces extending interfaces and for
enums implementing interfaces. Enum cases live in a separate table in
Zend and never conflict with inherited constants.
|
19 hours ago |