Summary
With Features::INTERCEPT_INITIALIZATIONS enabled, ConstructorExecutionTransformer rewrites every New_ node in a file — including new in initializers (PHP 8.1): parameter defaults, static variable initializers, and attribute arguments. A method call is not a valid constant expression, so the transformed file is a compile-time fatal.
Found during the PHP 8.5 support audit (PR #597). Reproduces on PHP 8.4 / 8.5.10 / 8.6.0beta2.
Reproduction
Input (tests/Fixtures/audit/src/Php81NewInInitializers.php):
public function run(Collaborator $helper = new Collaborator('method-default')): string
{
static $memo = new \ArrayObject();
...
Transformed output:
public function run(Collaborator $helper = \Go\Instrument\Transformer\ConstructorExecutionTransformer::getInstance()->{Collaborator::class}('method-default')): string
{
static $memo = \Go\Instrument\Transformer\ConstructorExecutionTransformer::getInstance()->{\ArrayObject::class}();
PHP Fatal error: Constant expression contains invalid operations
Root cause
src/Instrument/Transformer/ConstructorExecutionTransformer.php:60-88 — the FindingVisitor selects all Expr\New_ nodes with no context filter.
Proposed fix
Skip New_ nodes that appear in constant-expression context: while traversing, exclude nodes whose ancestors include Param->default, StaticVar->default, Const_/ClassConst, PropertyItem->default, EnumCase->expr, or Attribute args (a small NodeVisitor tracking these containers, or checking node attributes of the enclosing structure during the finding pass). Such new expressions run inside engine-managed initializer evaluation and cannot be intercepted — document that limitation (they still hit interception when the class itself is woven elsewhere at normal call sites).
Environment
- goaop/framework master (4.0-dev), PHP 8.4 / 8.5.10 / 8.6.0beta2
Summary
With
Features::INTERCEPT_INITIALIZATIONSenabled,ConstructorExecutionTransformerrewrites everyNew_node in a file — includingnewin initializers (PHP 8.1): parameter defaults, static variable initializers, and attribute arguments. A method call is not a valid constant expression, so the transformed file is a compile-time fatal.Found during the PHP 8.5 support audit (PR #597). Reproduces on PHP 8.4 / 8.5.10 / 8.6.0beta2.
Reproduction
Input (
tests/Fixtures/audit/src/Php81NewInInitializers.php):Transformed output:
Root cause
src/Instrument/Transformer/ConstructorExecutionTransformer.php:60-88— theFindingVisitorselects allExpr\New_nodes with no context filter.Proposed fix
Skip
New_nodes that appear in constant-expression context: while traversing, exclude nodes whose ancestors includeParam->default,StaticVar->default,Const_/ClassConst,PropertyItem->default,EnumCase->expr, orAttributeargs (a smallNodeVisitortracking these containers, or checking node attributes of the enclosing structure during the finding pass). Suchnewexpressions run inside engine-managed initializer evaluation and cannot be intercepted — document that limitation (they still hit interception when the class itself is woven elsewhere at normal call sites).Environment