From 54619a91edb7da0a6a809a2850fe922a8516d90b Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sat, 5 Sep 2026 15:21:10 +0200 Subject: [PATCH] Always parenthesize callable new expressions (`new T(...)`) This ensures they work as expected in all situations, including inside pipelines --- src/main/php/lang/ast/emit/PHP.class.php | 15 ++++----------- .../ast/unittest/emit/PipelinesTest.class.php | 11 +++++++++++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php index 4e3ae58e..c69ab4d4 100755 --- a/src/main/php/lang/ast/emit/PHP.class.php +++ b/src/main/php/lang/ast/emit/PHP.class.php @@ -7,7 +7,6 @@ ArrayLiteral, BinaryExpression, Block, - CallableNewExpression, Comment, Expression, InstanceExpression, @@ -1150,12 +1149,14 @@ protected function emitCallable($result, $callable) { protected function emitCallableNew($result, $callable) { $t= $result->temp(); - $result->out->write("fn(...{$t}) => "); + $result->out->write("(fn(...{$t}) => "); // See https://externals.io/message/129329 $callable->type->arguments= [new UnpackExpression(new Variable(substr($t, 1)), $callable->line)]; $this->emitOne($result, $callable->type); $callable->type->arguments= null; + + $result->out->write(')'); } protected function emitInvoke($result, $invoke) { @@ -1214,15 +1215,7 @@ protected function emitNullsafeInstance($result, $instance) { protected function emitPipe($result, $pipe) { $this->emitOne($result, $pipe->expression); $result->out->write('|>'); - - // `fn() => ...` on the right-hand side of pipe operator must be parenthesized - if ($pipe->target instanceof CallableNewExpression) { - $result->out->write('('); - $this->emitOne($result, $pipe->target); - $result->out->write(')'); - } else { - $this->emitOne($result, $pipe->target); - } + $this->emitOne($result, $pipe->target); } protected function emitNullsafePipe($result, $pipe) { diff --git a/src/test/php/lang/ast/unittest/emit/PipelinesTest.class.php b/src/test/php/lang/ast/unittest/emit/PipelinesTest.class.php index e20dd10b..d560baa2 100755 --- a/src/test/php/lang/ast/unittest/emit/PipelinesTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/PipelinesTest.class.php @@ -361,4 +361,15 @@ public function run() { Assert::equals("bool(false)\n", $r); } + + #[Test, Values([null, '2026-09-05'])] + public function nullable_pipe_to_callable_new($value) { + $r= $this->run('class %T { + public function run($value) { + return $value ?|> new \util\Date(...); + } + }', $value); + + Assert::equals($value, $r ? $r->toString('Y-m-d') : null); + } } \ No newline at end of file