- 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