-
-
Notifications
You must be signed in to change notification settings - Fork 205
Open
Description
Related to #1589
Analysis
The RFC had 2 proposals:
- Non-readonly classes can extend readonly classes in PHP 8.3: ❌ did not pass
- Readonly properties can be reinitialized during cloning in PHP 8.3: ✅ passed
Summary of existing PHP 8.2 behavior based on the RFC:
class Foo {
public function __construct(
public readonly string $bar,
public readonly string $baz
) {}
public function __clone()
{
unset($this->baz); // Fatal error
$this->bar = 'new value'; // Fatal error
}
}
$foo = new Foo('bar', 'baz');
clone $foo;Updated behavior in PHP 8.3:
class Foo {
public function __construct(
public readonly string $bar,
public readonly string $baz
) {}
public function __clone()
{
unset($this->baz); // Uninitializing is allowed
unset($this->baz); // Uninitializing a second time is allowed
$this->bar = 'new value'; // Reinitializing to a new value is allowed
$this->bar = 'new value'; // Fatal error: cannot reinitialize a second time, even if it's the same value
}
}
$foo = new Foo('bar', 'baz');
clone $foo;Top 2000 Packages
Detection in PHP 8.2
Assuming the property is readonly:
function __clone() { unset($this->bar); } Unset in __clone: error
function __clone() { $this->bar = 'new value'; } Assign in __clone: error
Detection in PHP 8.3
Assuming the property is readonly:
function __clone() { unset($this->bar); } Unset in __clone: valid
function __clone() { unset($this->bar); unset($this->bar); } Repeated unset in __clone: valid
function __clone() { $this->bar = 'new value'; } Assign in __clone: valid
function __clone() { $this->bar = 'new value'; $this->bar = 'new value'; } Repeated assign in __clone: error
Syntax Variations
- Readonly properties via constructor promotion
- Readonly properties via property declaration
- Readonly properties via readonly class
- Private visibility - has no impact
- Reflection-based assignment - same behavior as regular assignment
- Repeated unset and assign - different behavior between unset and assign when doing it more than once
- Deep cloning - clone an object property inside __clone (the RFC example)
- Reassign in other methods - forbidden in every version since readonly was introduced
- Invalid readonly or false positives are already covered in the original readonly sniff
Detectability
- Find readonly properties ✅ Already done in the original sniff
- Find assignment in __clone ✅❌ Partially doable, as __clone can call other methods in other files
- Find unsetting in __clone ✅❌ Partially doable, as __clone can call other methods in other files
References
Metadata
Metadata
Assignees
Labels
No labels