Repository navigation
Closed
Labels
area:compilerCompiler / CFG / JITCompiler / CFG / JITarea:vmVirtual machineVirtual machineenhancementNew feature or requestNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language featuresPhase 2 – language features
Description
Category
language | php-src-strict
Problem
Zend treats empty($obj->uninitTyped) and empty(Class::$uninitStatic) as true without throwing; isset() stays false. This compiler throws Error: Typed property … must not be accessed before initialization for empty() on both instance and static uninitialized typed properties.
Closed #4912 + compliance empty_uninitialized_typed_property.phpt codified the throw behavior; php-src parity requires reverting to Zend semantics and updating the compliance expectation.
php-src reference
- php/php-src
Zend/zend_object_handlers.c—empty()/isset()on typed properties (skip read when uninitialized) - php/php-src
ext/standard/basic_functions.c—PHP_EMPTY,PHP_ISSET - php/php-src
Zend/zend_types.h—IS_TYPE_UNINITIALIZEDguards
Repro (failure today)
<?php
class T {
public int $i;
public static int $s;
}
$t = new T();
echo 'isset i=', var_export(isset($t->i), true), ' empty i=', var_export(empty($t->i), true), PHP_EOL;
echo 'isset s=', var_export(isset(T::$s), true), ' empty s=', var_export(empty(T::$s), true), PHP_EOL;./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php repro.php
php bin/vm.php repro.php 2>&1
'| Line | Zend PHP 8.x | VM today |
|---|---|---|
instance isset / empty |
false / true |
false / fatal Error |
static isset / empty |
false / true |
fatal Error on empty |
Existing maintainer repro: test/repro/maintainer_empty_uninit_php_src.php (if present).
Scope (this repo)
| Path | Work |
|---|---|
| VM | lib/VM.php, EmptyObjectPropertyHelper — empty() must not invoke full read on uninitialized typed slots (instance + static) |
| JIT | lib/JIT/EmptyObjectPropertyHelper.php — same for TYPE_EMPTY_OBJECT_PROPERTY / static variants |
| AOT | Mirror JIT guards when lowered |
| Compliance | Update test/compliance/cases/language/empty_uninitialized_typed_property.phpt EXPECT to php-src output |
PHP-in-PHP: no runtime/*.c.
Done when
- Repro prints four lines matching Zend (
issetfalse,emptytrue) for instance and static - Direct read
$t->i/T::$sstill throwsError(unchanged) -
isset()behavior unchanged (already false) -
./script/ci-fast.sh --filter empty_uninitializedgreen on VM + JIT/AOT
Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter empty_uninitialized'Strictness
php-src-strict — default CI/compliance must match Zend, not #4912 throw semantics.
Related
- Language: empty() on uninitialized typed property must throw Error (zend_object_handlers.c) #4912 (closed — revert compliance) · Language: isset()/empty() on nullsafe ?-> chain — short-circuit like Zend (zend_compile.c) #4980 (isset on nullsafe) · Epic: Self-host critical path — compiler compiles itself (M3→M5) #1492
Metadata
Metadata
Assignees
Labels
area:compilerCompiler / CFG / JITCompiler / CFG / JITarea:vmVirtual machineVirtual machineenhancementNew feature or requestNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language featuresPhase 2 – language features
Activity
PurHur commentedon Jun 6, 2026
claim: worker-lane-b — starting this run
Fix empty() on uninitialized typed properties to match php-src (#6787) (
PurHur commentedon Jun 6, 2026
Merged via #6873
Fix:
empty()on uninitialized typed instance/static properties returnstruewithout throwing (php-src parity; reverts #4912 throw semantics).Verification:
```bash
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php test/repro/6787_empty_uninit_typed.php
php bin/vm.php test/repro/6787_empty_uninit_typed.php
vendor/bin/phpunit --filter empty_uninitialized
'
```
VM repro:
isset i=false empty i=true/isset s=false empty s=true— PHPUnit OK (2 tests, VM + JIT).