Problem
#1354 ✅ landed VM v1: attributes parse, lint, and compile; runtime ignores #[Attr] metadata. docs/roadmap-wave3.md and #1354 explicitly defer JIT/AOT reflection (ReflectionClass::getAttributes(), attribute targets on methods/properties).
Framework code and future self-host bundles may rely on reflection without Zend — today that path is VM-only or unsupported in native binaries.
Goal
| Layer |
Target |
| VM |
Optional: store attribute metadata on class/method nodes (not required for phase 2 if reflection is stubbed) |
| JIT |
Lower attribute tables for jittable units used in spine smoke |
| AOT |
Same metadata in linked binaries; Reflection* reads native tables |
Phase 2 scope: read path for ReflectionAttribute / getAttributes() on declared items — not full newInstance() with arbitrary attribute constructors.
Implementation hints
| Piece |
Path |
Notes |
| Parser |
vendor/ircmaxell/php-parser |
Already emits attribute nodes (#1354) |
| Compiler |
lib/Compiler.php |
Attach attribute list to class/method IR |
| VM |
lib/VM.php, lib/VM/Reflection*.php |
Backing store for reflection API |
| JIT |
lib/JIT.php |
Emit const attribute name/args blobs |
| AOT |
lib/AOT/ |
Link metadata section or globals |
| Tests |
test/compliance/cases/attribute_reflection_*.phpt |
Mirror Zend subset |
| Capabilities |
php script/capability-syntax.php |
Flip row from “ignored” to JIT/AOT yes |
Acceptance criteria
./phpc run test/compliance/cases/attribute_reflection_class.phpt
ATTRIBUTES_COMPLIANCE_GATE=1 ./script/ci-fast.sh --filter attribute_reflection
# When LLVM ready:
vendor/bin/phpunit --group llvm --filter AttributeReflection
Verification (local / Docker only)
docker run --rm -v "$(pwd):/compiler" -w /compiler php-compiler:22.04-dev \
./script/ci-fast.sh --filter attribute_reflection
No GitHub Actions.
Dependencies
Non-goals
- Arbitrary
newInstance() on attribute classes with complex ctor args
- Attributes on parameters (PHP 8.0+) in v1 phase 2
Links
Problem
#1354 ✅ landed VM v1: attributes parse, lint, and compile; runtime ignores
#[Attr]metadata.docs/roadmap-wave3.mdand #1354 explicitly defer JIT/AOT reflection (ReflectionClass::getAttributes(), attribute targets on methods/properties).Framework code and future self-host bundles may rely on reflection without Zend — today that path is VM-only or unsupported in native binaries.
Goal
Reflection*reads native tablesPhase 2 scope: read path for
ReflectionAttribute/getAttributes()on declared items — not fullnewInstance()with arbitrary attribute constructors.Implementation hints
vendor/ircmaxell/php-parserlib/Compiler.phplib/VM.php,lib/VM/Reflection*.phplib/JIT.phplib/AOT/test/compliance/cases/attribute_reflection_*.phptphp script/capability-syntax.phpAcceptance criteria
./phpc run test/compliance/cases/attribute_reflection_class.phpt ATTRIBUTES_COMPLIANCE_GATE=1 ./script/ci-fast.sh --filter attribute_reflection # When LLVM ready: vendor/bin/phpunit --group llvm --filter AttributeReflectionReflectionClass::getAttributes()returns count/name for#[Attr]on a compiled class in VM and AOT binarydocs/capabilities-syntax.md(deferred note removed)Verification (local / Docker only)
docker run --rm -v "$(pwd):/compiler" -w /compiler php-compiler:22.04-dev \ ./script/ci-fast.sh --filter attribute_reflectionNo GitHub Actions.
Dependencies
Non-goals
newInstance()on attribute classes with complex ctor argsLinks