Hi all,
I’d like to gauge interest in deprecating return inside a finally block, before I request karma to propose it as a full RFC.
A return inside a finally silently discards whatever the try/catch was doing…a pending exception or return value just disappears, with no error or notice.
As far as I know, it’s the only abrupt exit from a finally PHP leaves silent…
break/continue/goto out of one are already compile errors, and a throw auto-chains the discarded exception as $previous. Only return destroys the in-flight state and says nothing.
Looking into the history of finally I found that the author of the original RFC said he added it only because Java allowed it, even though he thought it made “no sense” https://externals.io/message/61670#61678
But Java itself warns about it (javac -Xlint:finally).
I also found that it was the source of a few bugs:
- https://bugs.php.net/bug.php?id=70228
- https://bugs.php.net/bug.php?id=72213
- https://github.com/php/php-src/issues/11028
To see what a change would actually cost, I implemented the deprecation and ran it over the top ~5000 Composer packages. And I found that it’s rare…there were only 12 occurrences across 9 packages out of 4992. Of those, 3 look like genuine latent bugs the deprecation caught, and the rest look deliberate.
Here’s the list of the occurrences:
- ibexa/admin-ui (swallows the exceptions its own docblock declares)
- shopware/core (eats thumbnail failures and still reports success)
- amphp/http-server (drops exceptions when the stream is already gone)
- dvdoug/PHPCoord (deliberate…finally is the method’s return)
- dvdoug/PHPCoord (again)
- dvdoug/PHPCoord (again)
- dvdoug/PHPCoord (again)
- spatie/ray (delibrate…any failure just returns false)
- cakephp/cakephp (catch consumed the exception…finally just returns array)
- hyperf/http-server (catch consumed the exception…finally emits response)
- silverstripe/framework (catch consumed the mysqli error)
- symfony/flex (try can’t actually throw)
My take here is that the language already handles the analogous cases (continue/break/goto/…etc) natively, so leaving return looks like an inconsistency.
I lean toward deprecating it now with an eye to an error in a future major (following the steps of Tim’s deprecate-return-from-constructor RFC)…though I guess a plain warning would be fine too. The main thing is that it seems worth doing something about.
Is there appetite for this?
Thanks,
Osama