- Rename canFoldLocalLiteralIntoDeclaration to canFoldLocalInitializerIntoDeclaration - Replace isDeclarationLiteral with isHoistSafeDeclarationInitializer - Add support for hoisting compile-time class constants in addition to literals - Implement isHoistSafeClassConstFetch to determine safe class constant hoisting - Add isHoistSafeConstFetch to validate constant fetch safety for hoisting - Update documentation to reflect hoist-safe value requirements - Add tests for native scalar literals, compile-time constants and class constants - Move internal constant value generation to separate method - Refine constant resolution logic with namespace fallback handling - Add validation for runtime constant dependencies in class constantsmaster
parent
d33073c021
commit
ab1854beb0
10 changed files with 435 additions and 57 deletions
@ -0,0 +1,42 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace LocalClassConstantInitializer; |
||||||
|
|
||||||
|
class BaseValues |
||||||
|
{ |
||||||
|
public const LIMIT = 128; |
||||||
|
} |
||||||
|
|
||||||
|
class Values extends BaseValues |
||||||
|
{ |
||||||
|
public const LABEL = 'typephp'; |
||||||
|
|
||||||
|
public function initialize(): void |
||||||
|
{ |
||||||
|
$selfValue = self::LABEL; |
||||||
|
$parentValue = parent::LIMIT; |
||||||
|
$concreteValue = Values::LABEL; |
||||||
|
$selfClass = self::class; |
||||||
|
$parentClass = parent::class; |
||||||
|
$unknownClass = MissingClass::class; |
||||||
|
|
||||||
|
$lateStatic = static::LABEL; |
||||||
|
$external = \DateTimeInterface::ATOM; |
||||||
|
$runtimeClassConstant = RuntimeProvider::VALUE; |
||||||
|
$class = Values::class; |
||||||
|
$dynamicClass = $class::LABEL; |
||||||
|
|
||||||
|
var_dump( |
||||||
|
$selfValue, |
||||||
|
$parentValue, |
||||||
|
$concreteValue, |
||||||
|
$selfClass, |
||||||
|
$parentClass, |
||||||
|
$unknownClass, |
||||||
|
$lateStatic, |
||||||
|
$external, |
||||||
|
$runtimeClassConstant, |
||||||
|
$dynamicClass, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace LocalConstantInitializer\Provider { |
||||||
|
const LIMIT = 64; |
||||||
|
const LABEL = 'known'; |
||||||
|
} |
||||||
|
|
||||||
|
namespace LocalConstantInitializer\Consumer { |
||||||
|
use const LocalConstantInitializer\Provider\LIMIT as IMPORTED_LIMIT; |
||||||
|
|
||||||
|
const ENABLED = true; |
||||||
|
|
||||||
|
function localConstantDeclarationInitializer(): void |
||||||
|
{ |
||||||
|
$imported = IMPORTED_LIMIT; |
||||||
|
$qualified = \LocalConstantInitializer\Provider\LABEL; |
||||||
|
$namespaced = ENABLED; |
||||||
|
$internal = \PHP_INT_MAX; |
||||||
|
|
||||||
|
define('LocalConstantInitializer\\Consumer\\RUNTIME_VALUE', 99); |
||||||
|
$runtime = RUNTIME_VALUE; |
||||||
|
|
||||||
|
// An unqualified internal constant in a namespace can be shadowed by |
||||||
|
// a namespaced define() before this statement executes. |
||||||
|
$namespaceFallback = PHP_VERSION_ID; |
||||||
|
|
||||||
|
var_dump( |
||||||
|
$imported, |
||||||
|
$qualified, |
||||||
|
$namespaced, |
||||||
|
$internal, |
||||||
|
$runtime, |
||||||
|
$namespaceFallback, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use native_types; |
||||||
|
|
||||||
|
function localLiteralDeclarationInitializerNative(): void |
||||||
|
{ |
||||||
|
$integer = 42; |
||||||
|
$negative = -7; |
||||||
|
$floating = 1.25; |
||||||
|
$boolean = true; |
||||||
|
$string = 'hello'; |
||||||
|
$nullValue = null; |
||||||
|
|
||||||
|
var_dump($integer, $negative, $floating, $boolean, $string, $nullValue); |
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
--TEST-- |
||||||
|
Only compile-time class constants initialize hoisted local declarations |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
class LocalClassConstantBase |
||||||
|
{ |
||||||
|
public const LIMIT = 128; |
||||||
|
} |
||||||
|
|
||||||
|
class LocalClassConstantValues extends LocalClassConstantBase |
||||||
|
{ |
||||||
|
public const LABEL = 'typephp'; |
||||||
|
|
||||||
|
public function read(): array |
||||||
|
{ |
||||||
|
$selfValue = self::LABEL; |
||||||
|
$parentValue = parent::LIMIT; |
||||||
|
$className = self::class; |
||||||
|
$lateStatic = static::LABEL; |
||||||
|
$external = \DateTimeInterface::ATOM; |
||||||
|
|
||||||
|
return [$selfValue, $parentValue, $className, $lateStatic, $external]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
var_dump((new LocalClassConstantValues())->read()); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
array(5) { |
||||||
|
[0]=> |
||||||
|
string(7) "typephp" |
||||||
|
[1]=> |
||||||
|
int(128) |
||||||
|
[2]=> |
||||||
|
string(24) "LocalClassConstantValues" |
||||||
|
[3]=> |
||||||
|
string(7) "typephp" |
||||||
|
[4]=> |
||||||
|
string(13) "Y-m-d\TH:i:sP" |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
--TEST-- |
||||||
|
Only compile-time constants initialize hoisted local declarations |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
namespace LocalConstantInitializer { |
||||||
|
const VALUE = 42; |
||||||
|
|
||||||
|
function readValues(): array |
||||||
|
{ |
||||||
|
$compiled = VALUE; |
||||||
|
$internal = \PHP_INT_MAX; |
||||||
|
|
||||||
|
define('LocalConstantInitializer\\RUNTIME_VALUE', 99); |
||||||
|
$runtime = RUNTIME_VALUE; |
||||||
|
|
||||||
|
return [$compiled, $internal === PHP_INT_MAX, $runtime]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
var_dump(\LocalConstantInitializer\readValues()); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
array(3) { |
||||||
|
[0]=> |
||||||
|
int(42) |
||||||
|
[1]=> |
||||||
|
bool(true) |
||||||
|
[2]=> |
||||||
|
int(99) |
||||||
|
} |
||||||
Loading…
Reference in new issue