rfc:engine_exceptions_for_php7
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:engine_exceptions_for_php7 [2014/09/30 20:17] – created nikic | rfc:engine_exceptions_for_php7 [2015/02/23 18:10] – goto vote nikic | ||
---|---|---|---|
Line 2: | Line 2: | ||
* Date: 2014-09-30 | * Date: 2014-09-30 | ||
* Author: Nikita Popov < | * Author: Nikita Popov < | ||
- | * Status: In Draft | + | * Status: In Voting |
* Proposed for: PHP 7 | * Proposed for: PHP 7 | ||
- | * Patch: https:// | ||
===== Introduction ===== | ===== Introduction ===== | ||
Line 13: | Line 12: | ||
<code php> | <code php> | ||
- | <?php | ||
- | |||
function call_method($obj) { | function call_method($obj) { | ||
$obj-> | $obj-> | ||
Line 22: | Line 19: | ||
</ | </ | ||
- | Currently the above code will throw a fatal error: | + | Currently the above code will throw a fatal error ((Since [[rfc: |
< | < | ||
Line 28: | Line 25: | ||
</ | </ | ||
- | This RFC replaces the fatal error with an '' | + | This RFC replaces the fatal error with an '' |
- | + | ||
- | < | + | |
- | Fatal error: Uncaught exception ' | + | |
- | Stack trace: | + | |
- | #0 / | + | |
- | #1 {main} | + | |
- | thrown in / | + | |
- | </ | + | |
- | + | ||
- | Of course | + | |
<code php> | <code php> | ||
Line 50: | Line 37: | ||
</ | </ | ||
- | Note: This RFC mostly matches | + | If the exception is not caught, PHP will continue to throw the same fatal error as it currently does. |
===== Motivation ===== | ===== Motivation ===== | ||
Line 68: | Line 55: | ||
E_RECOVERABLE_ERROR | E_RECOVERABLE_ERROR | ||
// Parse error | // Parse error | ||
- | |||
E_PARSE | E_PARSE | ||
Line 200: | Line 186: | ||
restore_error_handler(); | restore_error_handler(); | ||
</ | </ | ||
+ | |||
+ | === Performance === | ||
+ | |||
+ | The ability to bypass recoverable fatal errors while still continuing execution in the same code path may cause performance issues in some cases. For example it is currently possible to completely ignore argument type hints with an error handler. As such a JIT compiler may not be able to make strong assumptions about the types of type hinted parameters. | ||
==== Solution: Exceptions ==== | ==== Solution: Exceptions ==== | ||
Line 219: | Line 209: | ||
* It is now allowed to use exceptions in the engine. | * It is now allowed to use exceptions in the engine. | ||
- | * Existing errors of type '' | + | * Existing errors of type '' |
* It is discouraged to introduce new errors of type '' | * It is discouraged to introduce new errors of type '' | ||
- | The patch attached to this RFC already converts a large number of fatal and recoverable fatal errors to exceptions. It also converts parse errors to exceptions (there's only one of those). | + | In order to avoid updating many tests the current error messages will be retained if the engine/ |
+ | |||
+ | The patch attached to this RFC already converts a large number of fatal and recoverable fatal errors to exceptions. It also converts parse errors to exceptions. | ||
+ | |||
+ | ==== Hierarchy ==== | ||
+ | |||
+ | There is some concern that by extending '' | ||
+ | |||
+ | < | ||
+ | BaseExtension (abstract) | ||
+ | +- EngineException | ||
+ | +- ParseException | ||
+ | +- Exception | ||
+ | +- ErrorException | ||
+ | +- RuntimeException | ||
+ | +- ... | ||
+ | +- ... | ||
+ | </ | ||
+ | |||
+ | As such engine/ | ||
+ | |||
+ | Whether such a hierarchy (with a new '' | ||
===== Potential issues ===== | ===== Potential issues ===== | ||
Line 232: | Line 243: | ||
I have never seen this possibility used in practice outside some weird hacks (which use ignored recoverable type constraint errors to implement scalar typehints). In most cases custom error handlers throw an '' | I have never seen this possibility used in practice outside some weird hacks (which use ignored recoverable type constraint errors to implement scalar typehints). In most cases custom error handlers throw an '' | ||
- | ==== catch-all blocks in existing code ==== | + | ==== E_PARSE compatibility |
- | As '' | + | Currently parse errors generated during |
- | ==== Cluttered | + | As parse errors do not invoke the error handler, handling eval errors is tricky and requires code looking roughly as follows |
- | Going back to the code-sample from the introduction, this is the fatal error that is currently thrown: | + | <code php> |
+ | set_error_handler(function() { return false; }, 0); | ||
+ | @$undefinedVariable; | ||
+ | restore_error_handler(); | ||
- | < | + | $oldErrorReporting = error_reporting(); |
- | Fatal error: Call to a member function method() on a non-object in / | + | error_reporting($oldErrorReporting & ~E_PARSE); |
- | </code> | + | $result = eval($code); |
- | + | error_reporting($oldErrorReporting); | |
- | With this RFC the error changes into an uncaught exception: | + | |
- | < | + | $error = error_get_last(); |
- | Fatal error: Uncaught exception | + | if ($result === false && $error['type'] === E_PARSE) { |
- | Stack trace: | + | // Handle $error |
- | #0 /path/file.php(7): | + | } |
- | #1 {main} | + | |
- | thrown in / | + | |
</ | </ | ||
- | The uncaught exception message provides more information, | + | After this RFC errors should be handled as follows instead: |
- | I think it would be nice to make those messages a bit cleaner (for all exceptions). The following adjustment is simple to do and seems more readable to me: | + | < |
- | + | try { | |
- | < | + | |
- | Fatal error: Uncaught EngineException: | + | } catch (\ParseException $exception) { |
- | Stack trace: | + | // Handle $exception |
- | #0 / | + | } |
- | #1 {main} | + | |
- | thrown in / | + | |
- | </ | + | |
- | + | ||
- | Additional improvement | + | |
- | + | ||
- | < | + | |
- | Uncaught EngineException: | + | |
- | Stack trace: | + | |
- | #0 / | + | |
- | #1 {main} | + | |
</ | </ | ||
Line 301: | Line 301: | ||
The '' | The '' | ||
- | The '' | + | The '' |
===== Patch ===== | ===== Patch ===== | ||
- | A preliminary | + | A patch for this RFC is available at https:// |
The patch introduces basic infrastructure for this change, replaces '' | The patch introduces basic infrastructure for this change, replaces '' | ||
- | The patch does not yet contain all necessary test updates and is also not yet thoroughly tested. | + | To simplify porting to exceptions it is possible to throw engine exceptions by passing an additional '' |
+ | |||
+ | < | ||
+ | - zend_error_noreturn(E_ERROR, | ||
+ | + zend_error(E_EXCEPTION | E_ERROR, " | ||
+ | + FREE_UNFETCHED_OP1(); | ||
+ | + HANDLE_EXCEPTION(); | ||
+ | </ | ||
+ | |||
+ | The current | ||
===== Vote ===== | ===== Vote ===== | ||
+ | The primary vote decides if the proposal as outlined in the RFC is accepted and requires a 2/3 majority. | ||
+ | |||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
+ | |||
+ | The secondary vote decides whether or not a '' | ||
+ | |||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
+ | |||
+ | Voting started on 2015-02-23 and ends on 2015-03-08. |
rfc/engine_exceptions_for_php7.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1