PHP RFC: Support for anonymous catches
- Version: 1.0
- Date: 2013-06-25
- Author: Joost Koehoorn, joost.koehoorn@gmail.com
- Status: Inactive
- First Published at: http://wiki.php.net/rfc/anonymous_catch
Introduction
Currently, PHP requires all catch statements to specify an Exception
class and an identifier variable. This RFC proposes new language constructs to make the variable optional, and to have a fully anonymous catch-statement.
Proposal
With the recent addition of the finally
keyword for try-catch statements, PHP is now in line with many other languages such as C#, Python and Ruby (and probably many others). Those languages differ from PHP in that they don't require a variable to bind the exception in, and don't even require specifying a certain Exception class.
Thus, this RFC proposes to add syntax support for:
try { $this->connectToServer(); } catch (ConnectionLostException) { $this->retry(3); }
In this case, we don't need the exception object itself as the exception type is descriptive enough of what happened, and we do not need to log anything because the operation is tried again in 3 seconds. By not specifying a variable, we avoid the impression that we do actually need it. It also helps static analysis tools (e.g. as implemented in IDEs) more accurately discover unused variables.
We can take this one step further, to also get rid of the class:
try { $this->connectToServer(); } catch { $this->retry(3); }
This again avoids the impression that only a specific exception is catched, where currently the least-specific Exception
is used in many catch-statements, giving the indication that the handler is only for a specific type of exception, while it's not.
Note that there may only be one anonymous catch-statement, and it has to be the last one.
Advantages
- Better possibilities for static analysis tools
- Avoid indication of a specific exception type
- Runtime needs to perform less checks. No need to update the symboltable, no need to check exception inheritance.
- People from other languages such as C#, Python and Ruby expect this to work
Disadvantages
- The general consensus of the discussion in the mailinglist is that fully anonymous catches may encourage bad coding practices
Backward Incompatible Changes
Adding this syntax will not have any impact on existing code.
Proposed PHP Version(s)
As this is only a minor change in the codebase, this can be included in PHP 5.NEXT
Unaffected PHP Functionality
This change only requires changing the grammer file and the ZEND_CATCH
opcode has to be extended to allow for two UNUSED
arguments.
Proposed Voting Choices
I think I'd be best that the two syntax additions are voted for separately.
Patches and Tests
I have a working implementation for PHP 5.6.0-dev.
I also added six tests which all pass.
The code is mostly merge-ready, but I can't track down why the next opcode number is assigned in the class name zval for additional catches:
additional_catch: T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } catch_variable ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
It doesn't seem to be used later on in the compilation so I left it out for an additional anonymous catch. All Zend tests still pass.
There's some duplication for the anonymous catch-statements, as I can't see another way of assuring that anonymous catch-statements are always used as latest catch.