Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/CompilerVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -1332,13 +1332,13 @@ public static function supportsNewWithoutParensInConstAndStaticInitializers(): b
/**
* PHP 8.4+ dereferencable `new` without outer parentheses (`new Class()->m()`, RFC new_without_parentheses).
*
* Gated on {@see languageProfileVersion()} so 8.4.0-dev reference profile rejects like Zend 8.2
* (#19684, re-#6974). Forward profile: `PHP_COMPILER_PROFILE=8.4` or stable 8.4.0+.
* Forward profile on 8.4.0-dev builds and stable 8.4.0+ (#24755, #19684, re-#6974).
* Explicit `PHP_COMPILER_PROFILE=8.2` / `8.3` rejects like Zend ≤8.3.
* php-src: Zend/zend_language_parser.y — new_dereferenceable / new_non_dereferenceable.
*/
public static function supportsDereferencableNewWithoutOuterParens(): bool
{
return version_compare(self::languageProfileVersion(), '8.4.0', '>=');
return self::isForwardProfileAtLeast('8.4.0');
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
--TEST--
Language: dereferencable `new` without outer parentheses rejected on reference profile (#19684, Zend/zend_language_parser.y)
Language: dereferencable `new` without outer parentheses rejected on PROFILE=8.2 (#19684, #24755, Zend/zend_language_parser.y)
--SKIPIF--
<?php
if (!class_exists('PHPCompiler\\CompilerVersion')) {
require __DIR__ . '/../../../../vendor/autoload.php';
}
if (PHPCompiler\CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
die('skip dereferencable new enabled on PHP 8.4.0+ target');
$profile = getenv('PHP_COMPILER_PROFILE');
if (!\is_string($profile) || '8.2' !== trim($profile)) {
die('skip requires PHP_COMPILER_PROFILE=8.2 reference profile');
}
?>
--ENV--
PHP_COMPILER_PROFILE=8.2
--FILE--
<?php
class A { public function x(){ return 1; } }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
Language: `new Class()->method()` on default 8.4.0-dev forward profile (#24755, RFC new_without_parentheses)
--SKIPIF--
<?php
if (!class_exists('PHPCompiler\\CompilerVersion')) {
require __DIR__ . '/../../../../vendor/autoload.php';
}
if (!PHPCompiler\CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
die('skip requires PHP 8.4+ dereferencable new forward profile');
}
$profile = getenv('PHP_COMPILER_PROFILE');
if (\is_string($profile) && '' !== trim($profile) && '8.4' !== trim($profile)) {
die('skip requires unset PHP_COMPILER_PROFILE or PROFILE=8.4');
}
?>
--FILE--
<?php
class Builder {
public function build(): string { return 'built'; }
}
echo new Builder()->build(), "\n";
--EXPECT--
built
17 changes: 17 additions & 0 deletions test/repro/issue_24755_new_without_parens.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

/**
* Issue #24755 — PHP 8.4 `new` in expressions without outer parentheses.
*
* Run: php bin/vm.php test/repro/issue_24755_new_without_parens.php
*
* Zend reference: Zend/zend_language_parser.y (RFC new_without_parentheses)
*/

class Builder {
public function build(): string { return 'built'; }
}

echo new Builder()->build() . "\n";
19 changes: 17 additions & 2 deletions test/unit/CompilerVersionGateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1418,9 +1418,24 @@ public function testSupportsPhpBuildDateConstantTrueWhenProfile85(): void
}
}

public function testSupportsDereferencableNewWithoutOuterParensFalseOnReferenceProfile(): void
public function testSupportsDereferencableNewWithoutOuterParensTrueOn84DevForwardProfile(): void
{
$this->assertFalse(CompilerVersion::supportsDereferencableNewWithoutOuterParens());
$this->assertTrue(CompilerVersion::supportsDereferencableNewWithoutOuterParens());
}

public function testSupportsDereferencableNewWithoutOuterParensFalseWhenProfile82(): void
{
$prev = getenv('PHP_COMPILER_PROFILE');
putenv('PHP_COMPILER_PROFILE=8.2');
try {
$this->assertFalse(CompilerVersion::supportsDereferencableNewWithoutOuterParens());
} finally {
if (false === $prev) {
putenv('PHP_COMPILER_PROFILE');
} else {
putenv('PHP_COMPILER_PROFILE='.$prev);
}
}
}

public function testSupportsDereferencableNewWithoutOuterParensTrueWhenProfile84(): void
Expand Down
15 changes: 15 additions & 0 deletions test/unit/NewDereferenceableSyntaxRejectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public function testAllowsCtorParensObjectDerefOnForwardProfile(): void

public function testRejectsDereferencableNewOnReferenceProfile(): void
{
putenv('PHP_COMPILER_PROFILE=8.2');
if (CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
self::markTestSkipped('dereferencable new enabled on PHP 8.4.0+ target');
}
Expand All @@ -72,6 +73,7 @@ public function testRejectsDereferencableNewOnReferenceProfile(): void

public function testReferenceProfileSyntaxErrorLineAndMessage(): void
{
putenv('PHP_COMPILER_PROFILE=8.2');
if (CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
self::markTestSkipped('dereferencable new enabled on PHP 8.4.0+ target');
}
Expand All @@ -89,6 +91,7 @@ class A { public function x(){ return 1; } }

public function testNoOpForParenthesizedNew(): void
{
putenv('PHP_COMPILER_PROFILE=8.2');
if (CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
self::markTestSkipped('dereferencable new enabled on PHP 8.4.0+ target');
}
Expand All @@ -99,11 +102,23 @@ public function testNoOpForParenthesizedNew(): void

public function testDesugarNoOpWhenDisabled(): void
{
putenv('PHP_COMPILER_PROFILE=8.2');
if (CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
self::markTestSkipped('dereferencable new enabled on PHP 8.4.0+ target');
}

$src = '<?php echo new Greeter()->greet();';
self::assertSame($src, NewDereferenceableDesugar::desugar($src));
}

public function testAllowsCtorParensObjectDerefOnDefault84DevProfile(): void
{
putenv('PHP_COMPILER_PROFILE');
if (!CompilerVersion::supportsDereferencableNewWithoutOuterParens()) {
self::markTestSkipped('dereferencable new forward profile unavailable');
}

$code = '<?php echo new Greeter()->hello();';
self::assertSame($code, NewDereferenceableSyntaxRejector::reject($code, 'ok_new.php'));
}
}
Loading