Skip to content

fix(translator): trait member value comparison and adaptation validation - #60

Open
AlessioGiacobbe wants to merge 2 commits into
swoole:masterfrom
AlessioGiacobbe:split/trait-composition-checks
Open

fix(translator): trait member value comparison and adaptation validation#60
AlessioGiacobbe wants to merge 2 commits into
swoole:masterfrom
AlessioGiacobbe:split/trait-composition-checks

Conversation

@AlessioGiacobbe

Copy link
Copy Markdown
Contributor

Two trait-composition gaps:

  • Trait constant/property conflicts were compared by pretty-printed source text: two traits declaring const int X = 1 + 1; and const int X = 2; (or defaults spelled [1, 2] vs array(1, 2)) were rejected as conflicting, while Zend compares evaluated values. Values are now compared by evaluation — with Zend's declaration-time int→float coercion for float-typed members — falling back to source-text equality only when a value cannot be evaluated at compile time. Different values, visibility, or types still conflict.
  • Trait adaptations referencing nonexistent methods were silently ignored: use A { missing as g; } and use A, B { B::f insteadof A; } (with no B::f) both compiled — a typo in an adaptation did nothing. Every alias and precedence rule is now verified against the composed methods, with Zend's diagnostics; an unqualified alias is registered under every used trait, so its variants share one group satisfied by any match, and precedence rules also verify the named traits are actually used.

Verified against Zend 8.4.13; nested-trait aliasing covered.

Part of the split of #39.

Zend decides trait constant/property compatibility by comparing the
EVALUATED definition (zend_is_identical on the resolved zvals plus
matching flags and declared type), so `const int X = 1 + 1` in one
trait and `const int X = 2` in another are the same definition, as are
`[1, 2]` and `array(1, 2)` property defaults. composeTraitAst()
compared pretty-printed source text and isCompatibleTraitConstant()
compared lowered value strings, rejecting these valid compositions.

Evaluate both initializers with the existing evaluateClassConstValue()
machinery and compare with identity semantics (1 vs 1.0 or 1 vs '1'
still conflict, matching Zend), coercing an integer initializer to
float first when the member's declared type is float — Zend performs
that coercion at declaration time, so `public float $f = 1` and
`= 1.0` are identical. When a value cannot be evaluated at compile
time the previous source-text comparison remains as the fallback.
Flag, declared-type and (for properties) presence-of-default equality
checks are unchanged.
composeTraitAst() consumed matching traitAliases/traitIgnored entries
but never verified that every adaptation matched anything, silently
ignoring rules Zend rejects while binding traits:

  - `use A { missing as g; }` — "An alias (g) was defined for method
    missing(), but this method does not exist";
  - `use A { A::missing as g; }` — "An alias was defined for
    A::missing but this method does not exist";
  - an alias or precedence rule naming a trait outside the class's use
    list — "Required Trait B wasn't added to C";
  - `use A, B { B::f insteadof A; }` with no B::f — "A precedence
    rule was defined for B::f but this method does not exist" (the
    OVERRIDDEN trait need not declare the method — only the preferred
    one, matching Zend).

Composition now records which "trait::method" keys were seen (methods
arriving from nested traits are keyed under the directly-used trait,
matching how adaptations are registered) and validates every adaptation
afterwards. Because the Preprocessor registers an unqualified alias
under EVERY used trait's key, entries now carry the source adaptation's
group id — a group is satisfied when any variant matched — plus the
method name and explicit qualifier for diagnostics; precedence entries
record the rule for winner-existence validation (consumers only isset()
the key, so the value change is compatible).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant