Part of epic #219.
Feature
PHP 8.6 (Readonly Property Defaults RFC) lifts the restriction that readonly properties cannot declare default values:
final class CreateBooksTable implements MigratesUp
{
public readonly string $name = '2026-01-01_create_books_table';
}
Scope
- Ensure parsing a readonly property with a default value works end-to-end (PHP-Parser already parses the syntax; previously it was a compile error so the combination is untested here).
- Verify/fix the affected API surface in
src/ReflectionProperty.php and Traits/ReflectionClassLikeTrait.php:
hasDefaultValue() / getDefaultValue() on readonly properties
ReflectionClass::getDefaultProperties() including readonly defaults
- interaction with promoted readonly parameters and typed properties
- Check native 8.6 semantics for whether such a property still reports uninitialized-related behavior consistently and mirror it.
- Stub file with readonly defaults (plain, typed, const-expression defaults resolved by
NodeExpressionResolver, class constants, enum cases as defaults) + parity tests guarded for 8.6 runtime, direct assertions on 8.5.
Acceptance criteria
- Static results match native reflection on 8.6 for the whole stub matrix.
- PHPUnit green on 8.5, PHPStan level 10 clean.
Part of epic #219.
Feature
PHP 8.6 (Readonly Property Defaults RFC) lifts the restriction that
readonlyproperties cannot declare default values:Scope
src/ReflectionProperty.phpandTraits/ReflectionClassLikeTrait.php:hasDefaultValue()/getDefaultValue()on readonly propertiesReflectionClass::getDefaultProperties()including readonly defaultsNodeExpressionResolver, class constants, enum cases as defaults) + parity tests guarded for 8.6 runtime, direct assertions on 8.5.Acceptance criteria