__PHP_Incomplete_Class is a placeholder object that PHP creates when unserialize() hits a class it can't load. This RFC from Jordi Kroon would stop you from creating one yourself with new or copying one with clone.
Why change it
The class exists to mark a failure during unserialization. It stores the missing class name so you can see what went wrong. Creating one by hand, or cloning one, produces a state that never happens in normal use.
PHP already blocks some of this. You can't extend the class, and you can't create it through reflection paths that skip the constructor. This RFC closes the last two gaps.
Show me
Both of these would throw an Error:
// Uncaught Error: Instantiation of class __PHP_Incomplete_Class is not allowed new __PHP_Incomplete_Class(); // Uncaught Error: Trying to clone an uncloneable object of class __PHP_Incomplete_Class $incomplete = unserialize('O:16:"NonExistentClass":0:{}'); $clone = clone($incomplete);
Calling its constructor would be blocked as well, and ReflectionClass::isCloneable() would return false for the class.
If a test needs an incomplete object, it can still get one from unserialize():
$incomplete = unserialize('O:16:"NonExistentClass":0:{}');
What it means for existing code
Only code that creates or clones __PHP_Incomplete_Class directly would break, and it would need to call unserialize() with an unknown class name instead. Normal serialize and unserialize code isn't affected.
Extensions shouldn't be affected either. The RFC expects no performance cost, since it only adds checks when the object is created or cloned.
Where it stands
The RFC is under discussion, with PHP 8.6 as the target. The page has a vote set up, but no votes were cast, and the start and end dates in the text are still placeholders.