Skip to content

Intercepted promoted property with new-in-initializer default emits invalid hook property default #616

Description

@lisachenko

Summary

Follow-up to #599 (fixed in #613). The demotion approach correctly keeps a promoted parameter's default in the demoted constructor parameter — but the proxy hook property now copies that default verbatim. For a PHP 8.1 new-in-initializer default that's invalid: new is allowed in parameter defaults but not in property initializers.

Reproduction

class Php81NewInInitializers
{
    public function __construct(
        private Collaborator $service = new Collaborator('ctor-default'),
    ) {}
}

With a property advice on $service, the proxy contains:

private \Ns\Collaborator $service = new Collaborator('ctor-default') {
    get { ... }
PHP Fatal error: New expressions are not supported in this context

Reproduced by audit fixture tests/Stubs/Audit/Php81NewInInitializers.php (audit branch PR #597).

Proposed fix

In AbstractInterceptedPropertyGenerator (the default-from-Param logic added by #613): only carry the default onto the hook property when the expression is a valid property initializer — i.e. contains no New_ node (a small AST check; new is the only param-default construct excluded from property initializers). When skipped, the property stays uninitialized and still gets its value through the injected constructor assignment ($this->service = $service;), which the demotion already generates; the existing isInitialized() guard in the get hook handles the pre-construction window.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions