fix(translator): constructor, private-method and abstract redeclaration override rules - #56
Open
AlessioGiacobbe wants to merge 3 commits into
Open
Conversation
checkParentMethodCanBeOverridden() returned immediately for
__construct, so overriding a FINAL parent constructor was accepted
(Zend: "Cannot override final method A::__construct()") and an
ABSTRACT parent constructor's signature was never validated (Zend
checks it exactly like an interface constructor).
Zend's constructor rules (zend_do_inheritance):
- a concrete parent constructor imposes no signature contract: the
child may change parameters and even narrow visibility — this
exemption is kept;
- a private parent constructor may be redeclared freely, but FINAL
still wins: `final private function __construct()` cannot be
overridden (constructors are the one place PHP allows final
private);
- an abstract parent constructor's signature is a real contract.
Keep walking the parent chain for constructors, skipping only the
private-override error and the concrete-signature validation; final
checks (userland and built-in parents) and abstract-constructor
validation now run.
checkParentMethodCanBeOverridden() fataled with "Cannot override
private method" when a child declared a method whose nearest parent
declaration is PRIVATE. Zend inherits no private methods: a child may
redeclare one with any signature, visibility or staticness, and FINAL
is ignored on non-constructor private methods (declaring one only
raises "Private methods cannot be final..."). Only the final private
CONSTRUCTOR remains protected, which the constructor path already
enforces.
Dispatch stays correct after removing the fatal:
- canDevirtualize() (Parser/MethodCallTrait) devirtualizes any call
whose resolved method is private to the DECLARING class's body.
That is exactly PHP's private-scope binding (zend_std_get_method
prefers the calling scope's private copy), verified against the
manual's Bar/Foo::testPrivate example;
- method resolution walks from the receiver's static class, so code
in the child binds the child's redeclaration;
- a call on a receiver statically typed as the declaring class from
OUTSIDE its scope is rejected by getNativeMethod()'s accessibility
check, and dynamically typed receivers go through Zend dispatch;
- Native (C++) classes give private methods no virtual slot
(isNativeVirtualMethod() excludes PRIVATE), so no C++ override can
reroute a parent's internal private call.
The two tests asserting the old fatal encoded rejects-valid programs
(both run fine under Zend 8.4, printing the parent's private result);
they now assert successful compilation.
…parent chain An abstract method declared by a class was never checked against its parent: turning a concrete inherited method abstract compiled (Zend: "Cannot make non abstract method A::f() abstract in class B"), and an abstract redeclaration of an inherited abstract contract skipped the signature check entirely. Both now run through checkParentMethodCanBeOverridden with a childIsAbstract mode, covering userland and built-in parents. Trait-originated abstract requirements are exempt: Zend lets an inherited concrete method satisfy them, so only abstract methods the class itself declares participate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three gaps in the parent-method override checks, all in checkParentMethodCanBeOverridden:
__constructoverrides skipped every check via an early return — includingfinalparent constructors (Zend: "Cannot override final method A::__construct()") and abstract-constructor signature contracts. Ordinary concrete parent constructors remain exempt from LSP variance, as in Zend (even visibility narrowing is legal there — probed).Verified against Zend 8.4.13 for every rule and direction.
Part of the split of #39.