Req #78351 [Com]: Possible to check for invalid class

From: Date: Mon, 29 Jul 2019 18:36:55 +0000
Subject: Req #78351 [Com]: Possible to check for invalid class
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-222004@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78351&edit=1 ID: 78351 Comment by: nicolas dot grekas+php at gmail dot com Reported by: php at braten dot be Summary: Possible to check for invalid class Status: Open Type: Feature/Change Request Package: Scripting Engine problem Operating System: Irrelevant PHP Version: Next Minor Version Block user comment: N Private report: N New Comment: In https://github.com/symfony/symfony/issues/32395#issuecomment-509593220, Nikita gives us the following problematic example on 7.4: <quote> // A.php class A { public function foo($x): B {} } // B.php class B extends A { public function foo($x): C {} } // C.php class C extends B implements DoesNotExist { } // main.php new C; What happens now is the following: 1. Autoload C. The class C is registered provisionally. 2. Autoload the parent B. The class B is registered provisionally. 3.Autoload the parent A. The class A is registered provisionally. 4. The class A is verified (trivially) and registered fully. 5. The class B is verified and registered fully (and may already be used). During the verification it makes use of the fact that C is a subclass of B, otherwise the return types would not be covariant. 6. Autoload the interface DoesNotExist, which throws an exception. After these steps have happened ... what can we do now? We can't fully register the class C, because the interface it implements does not exist. We can't remove the provisionally registered class C either, because then a new class C that is not a subclass of B could be registered, and thus violate the variance assumption we made above. </quote> Then a commenter suggests: <quote> Would it be possible to mark a provisionally registered class as “in use” as soon as it is referenced somewhere? This way we could determine in an exception case if it is OK to remove the provisionally registered class and gracefully recover or if we have to throw a fatal error. In your example this would mean that once class B is verified it would mark class C as “in use”. When loading DoesNotExist throws the exception then, we would throw a fatal error because class C is “in use”. This way we could gracefully recover for most cases while resulting in a fatal error for the impossible cases, which sounds like a perfect trade-off to me. </quote> Implementing that proposal, if technically possible, would be enough to have code that provided the describe feature before 7.4 continue to work in most real-life situations. This is going to be a critical issue for Symfony at least, where this resiliency is pretty much needed. Thanks for considering. Previous Comments: ------------------------------------------------------------------------ [2019-07-29 18:14:07] php at braten dot be Description: ------------ It should be possible in PHP to check if a class exists or has a certain method without throwing a fatal error if the class is invalid. This has become an issue since https://bugs.php.net/bug.php?id=76980 was fixed, and is described in more detail in https://github.com/symfony/symfony/issues/32395 This is a feature request for the next version of PHP to allow functions like get_class_methods, get_class_vars, get_parent_class, is_a, is_subclass_of, class_exists, class_implements, class_parents, trait_exists, defined, interface_exists, method_exists, property_exists, is_callable to be called without throwing a *fatal* error if a class or interface does not exist. It can be ok if you later do "new" on the same class, that PHP must throw a fatal error. But it should be possible to get a negative result from the above mentioned functions without a fatal error. Test script: --------------- https://github.com/derrabus/symfony-32395-reproducer Expected result: ---------------- Possible to catch the error and resume. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=78351&edit=1

« previous php.bugs (#222004) next »